diff --git a/Perspex.sln b/Perspex.sln
index 2d1e4b3ed9..a6b425f9d1 100644
--- a/Perspex.sln
+++ b/Perspex.sln
@@ -140,6 +140,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.LeakTests", "tests\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{61BEC86C-F307-4295-B5B8-9428610D7D55}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.UnitTests", "tests\Perspex.UnitTests\Perspex.UnitTests.csproj", "{88060192-33D5-4932-B0F9-8BD2763E857D}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{fb05ac90-89ba-4f2f-a924-f37875fb547c}*SharedItemsImports = 4
@@ -148,19 +150,20 @@ Global
src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
src\Skia\Perspex.Skia\Perspex.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13
src\Shared\PlatformSupport\PlatformSupport.projitems*{db070a10-bf39-4752-8456-86e9d5928478}*SharedItemsImports = 4
- src\Shared\RenderHelpers\RenderHelpers.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
src\Skia\Perspex.Skia\Perspex.Skia.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
+ src\Shared\RenderHelpers\RenderHelpers.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
samples\TestApplicationShared\TestApplicationShared.projitems*{78345174-5b52-4a14-b9fd-d5f2428137f0}*SharedItemsImports = 13
src\Shared\PlatformSupport\PlatformSupport.projitems*{54f237d5-a70a-4752-9656-0c70b1a7b047}*SharedItemsImports = 4
samples\TestApplicationShared\TestApplicationShared.projitems*{ff69b927-c545-49ae-8e16-3d14d621aa12}*SharedItemsImports = 4
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
src\Shared\PlatformSupport\PlatformSupport.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4
- src\Shared\RenderHelpers\RenderHelpers.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
+ src\Shared\PlatformSupport\PlatformSupport.projitems*{88060192-33d5-4932-b0f9-8bd2763e857d}*SharedItemsImports = 4
src\Skia\Perspex.Skia\Perspex.Skia.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
+ src\Shared\RenderHelpers\RenderHelpers.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
samples\TestApplicationShared\TestApplicationShared.projitems*{8c923867-8a8f-4f6b-8b80-47d9e8436166}*SharedItemsImports = 4
samples\TestApplicationShared\TestApplicationShared.projitems*{e3a1060b-50d0-44e8-88b6-f44ef2e5bd72}*SharedItemsImports = 4
- src\Shared\RenderHelpers\RenderHelpers.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
src\Skia\Perspex.Skia\Perspex.Skia.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
+ src\Shared\RenderHelpers\RenderHelpers.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4
src\Shared\PlatformSupport\PlatformSupport.projitems*{e1aa3dbf-9056-4530-9376-18119a7a3ffe}*SharedItemsImports = 4
EndGlobalSection
@@ -1294,6 +1297,30 @@ Global
{61BEC86C-F307-4295-B5B8-9428610D7D55}.Release|iPhone.Build.0 = Release|Any CPU
{61BEC86C-F307-4295-B5B8-9428610D7D55}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{61BEC86C-F307-4295-B5B8-9428610D7D55}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.AppStore|Any CPU.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.AppStore|iPhone.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhone.Build.0 = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1338,5 +1365,6 @@ Global
{8C923867-8A8F-4F6B-8B80-47D9E8436166} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}
{E1AA3DBF-9056-4530-9376-18119A7A3FFE} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{61BEC86C-F307-4295-B5B8-9428610D7D55} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {88060192-33D5-4932-B0F9-8BD2763E857D} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
EndGlobal
diff --git a/docs/spec/architecture.md b/docs/spec/architecture.md
index a48a5a44dd..1e9e5a0321 100644
--- a/docs/spec/architecture.md
+++ b/docs/spec/architecture.md
@@ -31,7 +31,7 @@ The assemblies are as follows, from lowest to highest level:
The main classes in this assembly are `PerspexObject` and `PerspexProperty`.
-These are Perspex's versions of XAML's `DependencyObject` and `DepenendencyProperty`. It also
+These are Perspex's versions of XAML's `DependencyObject` and `DependencyProperty`. It also
defines a `PerspexDispatcher` which is - surprise - our version of XAML's `Dispatcher`.
### Perspex.Animation
diff --git a/nuget/template/Perspex.Android.nuspec b/nuget/template/Perspex.Android.nuspec
index 4cb1ad6a7c..5ee0174a43 100644
--- a/nuget/template/Perspex.Android.nuspec
+++ b/nuget/template/Perspex.Android.nuspec
@@ -13,15 +13,15 @@
Copyright 2015
Perspex
-
+
-
+
-
+
\ No newline at end of file
diff --git a/nuget/template/Perspex.Desktop.nuspec b/nuget/template/Perspex.Desktop.nuspec
index 192afe828d..7cde21cd90 100644
--- a/nuget/template/Perspex.Desktop.nuspec
+++ b/nuget/template/Perspex.Desktop.nuspec
@@ -13,18 +13,18 @@
Copyright 2015
Perspex
-
+
-
+
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/nuget/template/Perspex.Skia.Desktop.nuspec b/nuget/template/Perspex.Skia.Desktop.nuspec
index dcac0cdaf4..5203cd1409 100644
--- a/nuget/template/Perspex.Skia.Desktop.nuspec
+++ b/nuget/template/Perspex.Skia.Desktop.nuspec
@@ -13,7 +13,7 @@
Copyright 2015
Perspex
-
+
\ No newline at end of file
diff --git a/nuget/template/Perspex.iOS.nuspec b/nuget/template/Perspex.iOS.nuspec
index 568ee2bae1..f85d8be5c1 100644
--- a/nuget/template/Perspex.iOS.nuspec
+++ b/nuget/template/Perspex.iOS.nuspec
@@ -13,15 +13,15 @@
Copyright 2015
Perspex
-
+
-
+
-
+
\ No newline at end of file
diff --git a/nuget/template/Perspex.nuspec b/nuget/template/Perspex.nuspec
index ece9b0db9c..0339e1b2b8 100644
--- a/nuget/template/Perspex.nuspec
+++ b/nuget/template/Perspex.nuspec
@@ -13,9 +13,9 @@
Copyright 2015
Perspex
-
+
-
+
diff --git a/samples/TestApplication/App.config b/samples/TestApplication/App.config
index e354378dad..92abc44714 100644
--- a/samples/TestApplication/App.config
+++ b/samples/TestApplication/App.config
@@ -18,8 +18,16 @@
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/XamlTestApplication/App.config b/samples/XamlTestApplication/App.config
index 5ce331f23a..ccdb787c0f 100644
--- a/samples/XamlTestApplication/App.config
+++ b/samples/XamlTestApplication/App.config
@@ -17,9 +17,17 @@
+
+
+
+
-
+
+
+
+
+
diff --git a/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs b/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
index afb024b4cb..99971477c4 100644
--- a/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
+++ b/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
@@ -215,8 +215,6 @@ namespace Perspex.Cairo.Media
}
}
- private static Random Random = new Random();
-
///
/// Pushes a clip rectange.
///
diff --git a/src/Gtk/Perspex.Gtk/WindowImpl.cs b/src/Gtk/Perspex.Gtk/WindowImpl.cs
index 0e87911b80..d19f3a120c 100644
--- a/src/Gtk/Perspex.Gtk/WindowImpl.cs
+++ b/src/Gtk/Perspex.Gtk/WindowImpl.cs
@@ -379,10 +379,5 @@ namespace Perspex.Gtk
Input(e);
return true;
}
-
- private IPlatformHandle GetHandle(Gdk.Window window)
- {
- return new PlatformHandle(window.Handle, "GdkWindow");
- }
}
}
diff --git a/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs b/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
index 1d9d91d8e0..33ae02748b 100644
--- a/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
+++ b/src/Markup/Perspex.Markup.Xaml/Data/Binding.cs
@@ -226,21 +226,6 @@ namespace Perspex.Markup.Xaml.Data
return result;
}
- private IControl LookupNamedControl(IControl target)
- {
- Contract.Requires(target != null);
-
- var nameScope = target.FindNameScope();
-
- if (nameScope == null)
- {
- throw new InvalidOperationException(
- "Could not find name scope for ElementName binding.");
- }
-
- return nameScope.Find(ElementName);
- }
-
private class PathInfo
{
public string Path { get; set; }
diff --git a/src/Markup/Perspex.Markup/ControlLocator.cs b/src/Markup/Perspex.Markup/ControlLocator.cs
index 4887de8a15..730c4d24f9 100644
--- a/src/Markup/Perspex.Markup/ControlLocator.cs
+++ b/src/Markup/Perspex.Markup/ControlLocator.cs
@@ -22,15 +22,15 @@ namespace Perspex.Markup
/// The name of the control to find.
public static IObservable Track(IControl relativeTo, string name)
{
- var attached = Observable.FromEventPattern(
- x => relativeTo.AttachedToVisualTree += x,
- x => relativeTo.DetachedFromVisualTree += x)
+ var attached = Observable.FromEventPattern(
+ x => relativeTo.AttachedToLogicalTree += x,
+ x => relativeTo.DetachedFromLogicalTree += x)
.Select(x => ((IControl)x.Sender).FindNameScope())
.StartWith(relativeTo.FindNameScope());
- var detached = Observable.FromEventPattern(
- x => relativeTo.DetachedFromVisualTree += x,
- x => relativeTo.DetachedFromVisualTree += x)
+ var detached = Observable.FromEventPattern(
+ x => relativeTo.DetachedFromLogicalTree += x,
+ x => relativeTo.DetachedFromLogicalTree += x)
.Select(x => (INameScope)null);
return attached.Merge(detached).Select(nameScope =>
diff --git a/src/Perspex.Application/Application.cs b/src/Perspex.Application/Application.cs
index 177c337d04..e904207b18 100644
--- a/src/Perspex.Application/Application.cs
+++ b/src/Perspex.Application/Application.cs
@@ -59,12 +59,7 @@ namespace Perspex
throw new InvalidOperationException("Cannot create more than one Application instance.");
}
- Current = this;
- }
-
- public static void RegisterPlatformCallback(Action cb)
- {
- _platformInitializationCallback = cb;
+ PerspexLocator.CurrentMutable.BindToSelf(this);
}
///
@@ -75,8 +70,7 @@ namespace Perspex
///
public static Application Current
{
- get;
- private set;
+ get { return PerspexLocator.Current.GetService(); }
}
///
@@ -140,6 +134,11 @@ namespace Perspex
///
IStyleHost IStyleHost.StylingParent => null;
+ public static void RegisterPlatformCallback(Action cb)
+ {
+ _platformInitializationCallback = cb;
+ }
+
///
/// Runs the application's main loop until the is closed.
///
diff --git a/src/Perspex.Base/PerspexObject.cs b/src/Perspex.Base/PerspexObject.cs
index 5a0e1f5cf8..c1f1d246d0 100644
--- a/src/Perspex.Base/PerspexObject.cs
+++ b/src/Perspex.Base/PerspexObject.cs
@@ -678,16 +678,6 @@ namespace Perspex
}
}
- ///
- /// Gets a description of a property that van be used in observables.
- ///
- /// The property
- /// The description.
- private string GetDescription(PerspexProperty property)
- {
- return $"{GetType().Name}.{property.Name}";
- }
-
///
/// Gets a description of an observable that van be used in logs.
///
diff --git a/src/Perspex.Base/Threading/DispatcherTimer.cs b/src/Perspex.Base/Threading/DispatcherTimer.cs
index 1ece331c13..287ce1c124 100644
--- a/src/Perspex.Base/Threading/DispatcherTimer.cs
+++ b/src/Perspex.Base/Threading/DispatcherTimer.cs
@@ -181,6 +181,12 @@ namespace Perspex.Threading
if (!IsEnabled)
{
IPlatformThreadingInterface threading = PerspexLocator.Current.GetService();
+
+ if (threading == null)
+ {
+ throw new Exception("Could not start timer: IPlatformThreadingInterface is not registered.");
+ }
+
_timer = threading.StartTimer(Interval, InternalTick);
}
}
@@ -192,7 +198,6 @@ namespace Perspex.Threading
{
if (IsEnabled)
{
- IPlatformThreadingInterface threading = PerspexLocator.Current.GetService();
_timer.Dispose();
_timer = null;
}
diff --git a/src/Perspex.Controls/Button.cs b/src/Perspex.Controls/Button.cs
index 329456cbed..2ced7c4be8 100644
--- a/src/Perspex.Controls/Button.cs
+++ b/src/Perspex.Controls/Button.cs
@@ -211,7 +211,7 @@ namespace Perspex.Controls
}
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
diff --git a/src/Perspex.Controls/Carousel.cs b/src/Perspex.Controls/Carousel.cs
index 73d53ae6fc..fda48d0b42 100644
--- a/src/Perspex.Controls/Carousel.cs
+++ b/src/Perspex.Controls/Carousel.cs
@@ -74,7 +74,7 @@ namespace Perspex.Controls
}
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
// Ignore pointer presses.
}
diff --git a/src/Perspex.Controls/ContextMenu.cs b/src/Perspex.Controls/ContextMenu.cs
index c241a2dae0..861969547a 100644
--- a/src/Perspex.Controls/ContextMenu.cs
+++ b/src/Perspex.Controls/ContextMenu.cs
@@ -119,17 +119,6 @@
}
}
- private void PopupOpened(object sender, EventArgs e)
- {
- var selectedIndex = SelectedIndex;
-
- if (selectedIndex != -1)
- {
- var container = ItemContainerGenerator.ContainerFromIndex(selectedIndex);
- container?.Focus();
- }
- }
-
private static void ControlPointerReleased(object sender, PointerReleasedEventArgs e)
{
var control = (Control)sender;
diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs
index 74d67e0f4a..8a70ba201f 100644
--- a/src/Perspex.Controls/Control.cs
+++ b/src/Perspex.Controls/Control.cs
@@ -69,8 +69,7 @@ namespace Perspex.Controls
/// Defines the property.
///
public static readonly StyledProperty ContextMenuProperty =
- PerspexProperty.Register(nameof(ContextMenu));
-
+ PerspexProperty.Register(nameof(ContextMenu));
///
/// Event raised when an element wishes to be scrolled into view.
@@ -393,6 +392,15 @@ namespace Perspex.Controls
});
}
+ ///
+ /// Gets the element that recieves the focus adorner.
+ ///
+ /// The control that recieves the focus adorner.
+ protected virtual IControl GetTemplateFocusTarget()
+ {
+ return this;
+ }
+
///
/// Called when the control is added to a logical tree.
///
@@ -488,8 +496,13 @@ namespace Perspex.Controls
if (_focusAdorner != null)
{
- AdornerLayer.SetAdornedElement((Visual)_focusAdorner, this);
- adornerLayer.Children.Add(_focusAdorner);
+ var target = (Visual)GetTemplateFocusTarget();
+
+ if (target != null)
+ {
+ AdornerLayer.SetAdornedElement((Visual)_focusAdorner, target);
+ adornerLayer.Children.Add(_focusAdorner);
+ }
}
}
}
diff --git a/src/Perspex.Controls/DropDown.cs b/src/Perspex.Controls/DropDown.cs
index ed6ba1072f..7f8c1789ee 100644
--- a/src/Perspex.Controls/DropDown.cs
+++ b/src/Perspex.Controls/DropDown.cs
@@ -99,7 +99,7 @@ namespace Perspex.Controls
}
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
if (!IsDropDownOpen && ((IVisual)e.Source).GetVisualRoot() != typeof(PopupRoot))
{
diff --git a/src/Perspex.Controls/Grid.cs b/src/Perspex.Controls/Grid.cs
index dc25d29262..65bf029008 100644
--- a/src/Perspex.Controls/Grid.cs
+++ b/src/Perspex.Controls/Grid.cs
@@ -876,14 +876,6 @@ namespace Perspex.Controls
Stars = 0;
Type = type;
}
-
- public void Init(double offeredSize, double min, double max, GridUnitType type)
- {
- OfferedSize = offeredSize;
- Min = min;
- Max = max;
- Type = type;
- }
}
private struct GridNode
diff --git a/src/Perspex.Controls/IControl.cs b/src/Perspex.Controls/IControl.cs
index 0e65c599be..a76fda9c01 100644
--- a/src/Perspex.Controls/IControl.cs
+++ b/src/Perspex.Controls/IControl.cs
@@ -1,6 +1,7 @@
// 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.Templates;
using Perspex.Input;
using Perspex.Layout;
@@ -13,6 +14,16 @@ namespace Perspex.Controls
///
public interface IControl : IVisual, ILogical, ILayoutable, IInputElement, INamed, IStyleable, IStyleHost
{
+ ///
+ /// Raised when the control is attached to a rooted logical tree.
+ ///
+ event EventHandler AttachedToLogicalTree;
+
+ ///
+ /// Raised when the control is detached from a rooted logical tree.
+ ///
+ event EventHandler DetachedFromLogicalTree;
+
///
/// Gets or sets the control's styling classes.
///
diff --git a/src/Perspex.Controls/ListBox.cs b/src/Perspex.Controls/ListBox.cs
index 3cb66641ac..7bd3aa70d1 100644
--- a/src/Perspex.Controls/ListBox.cs
+++ b/src/Perspex.Controls/ListBox.cs
@@ -59,7 +59,7 @@ namespace Perspex.Controls
}
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
diff --git a/src/Perspex.Controls/Menu.cs b/src/Perspex.Controls/Menu.cs
index 682789be8e..099f4e2345 100644
--- a/src/Perspex.Controls/Menu.cs
+++ b/src/Perspex.Controls/Menu.cs
@@ -211,7 +211,7 @@ namespace Perspex.Controls
///
/// The sender.
/// The event args.
- private void TopLevelPreviewPointerPress(object sender, PointerPressEventArgs e)
+ private void TopLevelPreviewPointerPress(object sender, PointerPressedEventArgs e)
{
if (IsOpen)
{
diff --git a/src/Perspex.Controls/MenuItem.cs b/src/Perspex.Controls/MenuItem.cs
index ad03a1303f..36663ddfb9 100644
--- a/src/Perspex.Controls/MenuItem.cs
+++ b/src/Perspex.Controls/MenuItem.cs
@@ -310,7 +310,7 @@ namespace Perspex.Controls
/// Called when the pointer is pressed over the .
///
/// The event args.
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
@@ -447,13 +447,6 @@ namespace Perspex.Controls
///
public static readonly DependencyResolver Instance = new DependencyResolver();
- ///
- /// Disposes of all managed resources.
- ///
- public void Dispose()
- {
- }
-
///
/// Gets a service of the specified type.
///
diff --git a/src/Perspex.Controls/Mixins/ContentControlMixin.cs b/src/Perspex.Controls/Mixins/ContentControlMixin.cs
index 2435a266f7..a935fafc00 100644
--- a/src/Perspex.Controls/Mixins/ContentControlMixin.cs
+++ b/src/Perspex.Controls/Mixins/ContentControlMixin.cs
@@ -118,13 +118,6 @@ namespace Perspex.Controls.Mixins
});
}
- private static event EventHandler TemplateApplied;
-
- private static void OnTemplateApplied(object sender, RoutedEventArgs e)
- {
- TemplateApplied?.Invoke(sender, (TemplateAppliedEventArgs)e);
- }
-
private static void UpdateLogicalChild(
IControl control,
IPerspexList logicalChildren,
diff --git a/src/Perspex.Controls/Mixins/SelectableMixin.cs b/src/Perspex.Controls/Mixins/SelectableMixin.cs
index 21b04f9702..4d1e5bb25f 100644
--- a/src/Perspex.Controls/Mixins/SelectableMixin.cs
+++ b/src/Perspex.Controls/Mixins/SelectableMixin.cs
@@ -50,11 +50,14 @@ namespace Perspex.Controls.Mixins
if (sender != null)
{
+ var itemsControl = sender.Parent as SelectingItemsControl;
+
if ((bool)x.NewValue)
{
((IPseudoClasses)sender.Classes).Add(":selected");
- if (((IVisual)sender).IsAttachedToVisualTree)
+ if (((IVisual)sender).IsAttachedToVisualTree &&
+ itemsControl?.AutoScrollToSelectedItem == true)
{
sender.BringIntoView();
}
diff --git a/src/Perspex.Controls/Platform/PlatformManager.cs b/src/Perspex.Controls/Platform/PlatformManager.cs
index 75cd4e4cd3..17a3ff691f 100644
--- a/src/Perspex.Controls/Platform/PlatformManager.cs
+++ b/src/Perspex.Controls/Platform/PlatformManager.cs
@@ -192,8 +192,14 @@ namespace Perspex.Controls.Platform
public static IWindowImpl CreateWindow()
{
var platform = PerspexLocator.Current.GetService();
- return
- new WindowDecorator(s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow());
+
+ if (platform == null)
+ {
+ throw new Exception("Could not CreateWindow(): IWindowingPlatform is not registered.");
+ }
+
+ var window = s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow();
+ return new WindowDecorator(window);
}
public static IPopupImpl CreatePopup()
diff --git a/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs b/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs
index 1b60e1c834..d9af0b3b6e 100644
--- a/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Perspex.Controls/Presenters/ScrollContentPresenter.cs
@@ -256,13 +256,5 @@ namespace Perspex.Controls.Presenters
Extent = scrollable.Extent;
Offset = scrollable.Offset;
}
-
- private static Vector ValidateOffset(ScrollContentPresenter o, Vector value)
- {
- return ScrollViewer.CoerceOffset(
- o.GetValue(ExtentProperty),
- o.GetValue(ViewportProperty),
- value);
- }
}
}
diff --git a/src/Perspex.Controls/Primitives/Popup.cs b/src/Perspex.Controls/Primitives/Popup.cs
index ffa739dd70..80a7dfeae4 100644
--- a/src/Perspex.Controls/Primitives/Popup.cs
+++ b/src/Perspex.Controls/Primitives/Popup.cs
@@ -288,7 +288,7 @@ namespace Perspex.Controls.Primitives
}
}
- private void PointerPressedOutside(object sender, PointerPressEventArgs e)
+ private void PointerPressedOutside(object sender, PointerPressedEventArgs e)
{
if (!StaysOpen)
{
diff --git a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs
index c271bbd900..9ec708dd6b 100644
--- a/src/Perspex.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Perspex.Controls/Primitives/SelectingItemsControl.cs
@@ -38,6 +38,14 @@ namespace Perspex.Controls.Primitives
///
public class SelectingItemsControl : ItemsControl
{
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty AutoScrollToSelectedItemProperty =
+ PerspexProperty.Register(
+ nameof(AutoScrollToSelectedItem),
+ defaultValue: true);
+
///
/// Defines the property.
///
@@ -123,6 +131,15 @@ namespace Perspex.Controls.Primitives
remove { RemoveHandler(SelectionChangedEvent, value); }
}
+ ///
+ /// Gets or sets a value indicating whether to automatically scroll to newly selected items.
+ ///
+ public bool AutoScrollToSelectedItem
+ {
+ get { return GetValue(AutoScrollToSelectedItemProperty); }
+ set { SetValue(AutoScrollToSelectedItemProperty, value); }
+ }
+
///
/// Gets or sets the index of the selected item.
///
diff --git a/src/Perspex.Controls/Primitives/TabStrip.cs b/src/Perspex.Controls/Primitives/TabStrip.cs
index 1cfb4e0515..8c35bd609a 100644
--- a/src/Perspex.Controls/Primitives/TabStrip.cs
+++ b/src/Perspex.Controls/Primitives/TabStrip.cs
@@ -35,7 +35,7 @@ namespace Perspex.Controls.Primitives
}
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
diff --git a/src/Perspex.Controls/Primitives/TemplatedControl.cs b/src/Perspex.Controls/Primitives/TemplatedControl.cs
index 0941864ae4..7c3d7dd7cf 100644
--- a/src/Perspex.Controls/Primitives/TemplatedControl.cs
+++ b/src/Perspex.Controls/Primitives/TemplatedControl.cs
@@ -74,6 +74,12 @@ namespace Perspex.Controls.Primitives
public static readonly StyledProperty TemplateProperty =
PerspexProperty.Register("Template");
+ ///
+ /// Defines the IsTemplateFocusTarget attached property.
+ ///
+ public static readonly AttachedProperty IsTemplateFocusTargetProperty =
+ PerspexProperty.RegisterAttached("IsTemplateFocusTarget");
+
///
/// Defines the routed event.
///
@@ -198,6 +204,33 @@ namespace Perspex.Controls.Primitives
set { SetValue(TemplateProperty, value); }
}
+ ///
+ /// Gets the value of the IsTemplateFocusTargetProperty attached property on a control.
+ ///
+ /// The control.
+ /// The property value.
+ ///
+ public bool GetIsTemplateFocusTarget(Control control)
+ {
+ return control.GetValue(IsTemplateFocusTargetProperty);
+ }
+
+ ///
+ /// Sets the value of the IsTemplateFocusTargetProperty attached property on a control.
+ ///
+ /// The control.
+ /// The property value.
+ ///
+ /// When a control is navigated to using the keyboard, a focus adorner is shown - usually
+ /// around the control itself. However if the TemplatedControl.IsTemplateFocusTarget
+ /// attached property is set to true on an element in the control template, then the focus
+ /// adorner will be shown around that control instead.
+ ///
+ public void SetIsTemplateFocusTarget(Control control, bool value)
+ {
+ control.SetValue(IsTemplateFocusTargetProperty, value);
+ }
+
///
public sealed override void ApplyTemplate()
{
@@ -224,6 +257,7 @@ namespace Perspex.Controls.Primitives
}
}
+ ///
protected sealed override IndexerDescriptor CreateBindingDescriptor(IndexerDescriptor source)
{
var result = base.CreateBindingDescriptor(source);
@@ -240,6 +274,20 @@ namespace Perspex.Controls.Primitives
return result;
}
+ ///
+ protected override IControl GetTemplateFocusTarget()
+ {
+ foreach (Control child in this.GetTemplateChildren())
+ {
+ if (GetIsTemplateFocusTarget(child))
+ {
+ return child;
+ }
+ }
+
+ return this;
+ }
+
///
/// Called when the control's template is applied.
///
diff --git a/src/Perspex.Controls/Primitives/Thumb.cs b/src/Perspex.Controls/Primitives/Thumb.cs
index 01e5c19d84..9f6318fb7e 100644
--- a/src/Perspex.Controls/Primitives/Thumb.cs
+++ b/src/Perspex.Controls/Primitives/Thumb.cs
@@ -72,7 +72,7 @@ namespace Perspex.Controls.Primitives
}
}
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
e.Device.Capture(this);
_lastPoint = e.GetPosition(this);
diff --git a/src/Perspex.Controls/Templates/TemplateExtensions.cs b/src/Perspex.Controls/Templates/TemplateExtensions.cs
index 40672f873e..018ec033fd 100644
--- a/src/Perspex.Controls/Templates/TemplateExtensions.cs
+++ b/src/Perspex.Controls/Templates/TemplateExtensions.cs
@@ -12,21 +12,30 @@ namespace Perspex.Controls.Templates
{
public static class TemplateExtensions
{
- public static IEnumerable GetTemplateChildren(this ITemplatedControl control)
+ public static IEnumerable GetTemplateChildren(this ITemplatedControl control)
{
- var visual = control as IVisual;
-
- if (visual != null)
+ foreach (IControl child in GetTemplateChildren((IControl)control, control))
{
- // TODO: This searches the whole descendent tree - it can stop when it exits the
- // template.
- return visual.GetVisualDescendents()
- .OfType()
- .Where(x => x.TemplatedParent == control);
+ yield return child;
}
- else
+ }
+
+ private static IEnumerable GetTemplateChildren(IControl control, ITemplatedControl templatedParent)
+ {
+ foreach (IControl child in control.GetVisualChildren())
{
- return Enumerable.Empty();
+ if (child.TemplatedParent == templatedParent)
+ {
+ yield return child;
+ }
+
+ if (child.TemplatedParent != null)
+ {
+ foreach (var descendent in GetTemplateChildren(child, templatedParent))
+ {
+ yield return descendent;
+ }
+ }
}
}
}
diff --git a/src/Perspex.Controls/TextBox.cs b/src/Perspex.Controls/TextBox.cs
index 2bf51b2ad3..8a0aece63d 100644
--- a/src/Perspex.Controls/TextBox.cs
+++ b/src/Perspex.Controls/TextBox.cs
@@ -51,6 +51,9 @@ namespace Perspex.Controls
public static readonly StyledProperty UseFloatingWatermarkProperty =
PerspexProperty.Register("UseFloatingWatermark");
+ public static readonly StyledProperty IsReadOnlyProperty =
+ PerspexProperty.Register(nameof(IsReadOnly));
+
struct UndoRedoState : IEquatable
{
public string Text { get; }
@@ -154,6 +157,12 @@ namespace Perspex.Controls
set { SetValue(UseFloatingWatermarkProperty, value); }
}
+ public bool IsReadOnly
+ {
+ get { return GetValue(IsReadOnlyProperty); }
+ set { SetValue(IsReadOnlyProperty, value); }
+ }
+
public TextWrapping TextWrapping
{
get { return GetValue(TextWrappingProperty); }
@@ -187,17 +196,20 @@ namespace Perspex.Controls
private void HandleTextInput(string input)
{
- string text = Text ?? string.Empty;
- int caretIndex = CaretIndex;
- if (!string.IsNullOrEmpty(input))
+ if (!IsReadOnly)
{
- DeleteSelection();
- caretIndex = CaretIndex;
- text = Text ?? string.Empty;
- Text = text.Substring(0, caretIndex) + input + text.Substring(caretIndex);
- CaretIndex += input.Length;
- SelectionStart = SelectionEnd = CaretIndex;
- _undoRedoHelper.DiscardRedo();
+ string text = Text ?? string.Empty;
+ int caretIndex = CaretIndex;
+ if (!string.IsNullOrEmpty(input))
+ {
+ DeleteSelection();
+ caretIndex = CaretIndex;
+ text = Text ?? string.Empty;
+ Text = text.Substring(0, caretIndex) + input + text.Substring(caretIndex);
+ CaretIndex += input.Length;
+ SelectionStart = SelectionEnd = CaretIndex;
+ _undoRedoHelper.DiscardRedo();
+ }
}
}
@@ -343,7 +355,7 @@ namespace Perspex.Controls
}
}
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
if (e.Source == _presenter)
{
@@ -510,21 +522,28 @@ namespace Perspex.Controls
private bool DeleteSelection()
{
- var selectionStart = SelectionStart;
- var selectionEnd = SelectionEnd;
-
- if (selectionStart != selectionEnd)
+ if (!IsReadOnly)
{
- var start = Math.Min(selectionStart, selectionEnd);
- var end = Math.Max(selectionStart, selectionEnd);
- var text = Text;
- Text = text.Substring(0, start) + text.Substring(end);
- SelectionStart = SelectionEnd = CaretIndex = start;
- return true;
+ var selectionStart = SelectionStart;
+ var selectionEnd = SelectionEnd;
+
+ if (selectionStart != selectionEnd)
+ {
+ var start = Math.Min(selectionStart, selectionEnd);
+ var end = Math.Max(selectionStart, selectionEnd);
+ var text = Text;
+ Text = text.Substring(0, start) + text.Substring(end);
+ SelectionStart = SelectionEnd = CaretIndex = start;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
else
{
- return false;
+ return true;
}
}
diff --git a/src/Perspex.Controls/TreeView.cs b/src/Perspex.Controls/TreeView.cs
index 6fe61be20a..b86200e103 100644
--- a/src/Perspex.Controls/TreeView.cs
+++ b/src/Perspex.Controls/TreeView.cs
@@ -22,9 +22,7 @@ namespace Perspex.Controls
/// Defines the property.
///
public static readonly StyledProperty AutoScrollToSelectedItemProperty =
- PerspexProperty.Register(
- nameof(AutoScrollToSelectedItem),
- defaultValue: true);
+ SelectingItemsControl.AutoScrollToSelectedItemProperty.AddOwner();
///
/// Defines the property.
@@ -118,7 +116,7 @@ namespace Perspex.Controls
}
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
diff --git a/src/Perspex.HtmlRenderer/HtmlControl.cs b/src/Perspex.HtmlRenderer/HtmlControl.cs
index 9e4c8c0540..97d7c517e5 100644
--- a/src/Perspex.HtmlRenderer/HtmlControl.cs
+++ b/src/Perspex.HtmlRenderer/HtmlControl.cs
@@ -401,7 +401,7 @@ namespace Perspex.Controls.Html
///
/// Handle mouse down to handle selection.
///
- protected override void OnPointerPressed(PointerPressEventArgs e)
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
LeftMouseButton = true;
diff --git a/src/Perspex.Input/Cursors.cs b/src/Perspex.Input/Cursors.cs
index 34f97fe0a6..184bfd38b0 100644
--- a/src/Perspex.Input/Cursors.cs
+++ b/src/Perspex.Input/Cursors.cs
@@ -56,12 +56,22 @@ namespace Perspex.Input
}
public Cursor(StandardCursorType cursorType)
- : this(
- ((IStandardCursorFactory)PerspexLocator.Current.GetService(typeof(IStandardCursorFactory))).GetCursor(
- cursorType))
+ : this(GetCursor(cursorType))
{
}
public IPlatformHandle PlatformCursor { get; }
+
+ private static IPlatformHandle GetCursor(StandardCursorType type)
+ {
+ var platform = PerspexLocator.Current.GetService();
+
+ if (platform == null)
+ {
+ throw new Exception("Could not create Cursor: IStandardCursorFactory not registered.");
+ }
+
+ return platform.GetCursor(type);
+ }
}
}
diff --git a/src/Perspex.Input/FocusManager.cs b/src/Perspex.Input/FocusManager.cs
index 530f8c05bd..1ce645fd13 100644
--- a/src/Perspex.Input/FocusManager.cs
+++ b/src/Perspex.Input/FocusManager.cs
@@ -175,7 +175,7 @@ namespace Perspex.Input
{
if (sender == e.Source)
{
- var ev = (PointerPressEventArgs)e;
+ var ev = (PointerPressedEventArgs)e;
var element = (ev.Device.Captured as IInputElement) ?? (e.Source as IInputElement);
if (element == null || !CanFocus(element))
diff --git a/src/Perspex.Input/IInputElement.cs b/src/Perspex.Input/IInputElement.cs
index e8658c99b0..c40087ca86 100644
--- a/src/Perspex.Input/IInputElement.cs
+++ b/src/Perspex.Input/IInputElement.cs
@@ -51,7 +51,7 @@ namespace Perspex.Input
///
/// Occurs when the pointer is pressed over the control.
///
- event EventHandler PointerPressed;
+ event EventHandler PointerPressed;
///
/// Occurs when the pointer moves over the control.
diff --git a/src/Perspex.Input/InputElement.cs b/src/Perspex.Input/InputElement.cs
index e47412bdee..dab429cbdf 100644
--- a/src/Perspex.Input/InputElement.cs
+++ b/src/Perspex.Input/InputElement.cs
@@ -116,8 +116,8 @@ namespace Perspex.Input
///
/// Defines the event.
///
- public static readonly RoutedEvent PointerPressedEvent =
- RoutedEvent.Register(
+ public static readonly RoutedEvent PointerPressedEvent =
+ RoutedEvent.Register(
"PointerPressed",
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
@@ -235,7 +235,7 @@ namespace Perspex.Input
///
/// Occurs when the pointer is pressed over the control.
///
- public event EventHandler PointerPressed
+ public event EventHandler PointerPressed
{
add { AddHandler(PointerPressedEvent, value); }
remove { RemoveHandler(PointerPressedEvent, value); }
@@ -437,7 +437,7 @@ namespace Perspex.Input
/// Called before the event occurs.
///
/// The event args.
- protected virtual void OnPointerPressed(PointerPressEventArgs e)
+ protected virtual void OnPointerPressed(PointerPressedEventArgs e)
{
}
diff --git a/src/Perspex.Input/KeyboardDevice.cs b/src/Perspex.Input/KeyboardDevice.cs
index 421a09eaba..87d7b9c02c 100644
--- a/src/Perspex.Input/KeyboardDevice.cs
+++ b/src/Perspex.Input/KeyboardDevice.cs
@@ -83,6 +83,7 @@ namespace Perspex.Input
if (element != null)
{
var keyInput = e as RawKeyEventArgs;
+
if (keyInput != null)
{
switch (keyInput.Type)
@@ -117,19 +118,25 @@ namespace Perspex.Input
}
element.RaiseEvent(ev);
+ e.Handled = ev.Handled;
break;
}
}
+
var text = e as RawTextInputEventArgs;
+
if (text != null)
{
- element.RaiseEvent(new TextInputEventArgs()
+ var ev = new TextInputEventArgs()
{
Device = this,
Text = text.Text,
Source = element,
RoutedEvent = InputElement.TextInputEvent
- });
+ };
+
+ element.RaiseEvent(ev);
+ e.Handled = ev.Handled;
}
}
}
diff --git a/src/Perspex.Input/MouseDevice.cs b/src/Perspex.Input/MouseDevice.cs
index df30b06644..03329df2e4 100644
--- a/src/Perspex.Input/MouseDevice.cs
+++ b/src/Perspex.Input/MouseDevice.cs
@@ -115,7 +115,7 @@ namespace Perspex.Input
case RawMouseEventType.LeftButtonDown:
case RawMouseEventType.RightButtonDown:
case RawMouseEventType.MiddleButtonDown:
- MouseDown(mouse, e.Timestamp, e.Root, e.Position,
+ e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position,
e.Type == RawMouseEventType.LeftButtonDown
? MouseButton.Left
: e.Type == RawMouseEventType.RightButtonDown ? MouseButton.Right : MouseButton.Middle,
@@ -124,17 +124,17 @@ namespace Perspex.Input
case RawMouseEventType.LeftButtonUp:
case RawMouseEventType.RightButtonUp:
case RawMouseEventType.MiddleButtonUp:
- MouseUp(mouse, e.Root, e.Position,
+ e.Handled = MouseUp(mouse, e.Root, e.Position,
e.Type == RawMouseEventType.LeftButtonUp
? MouseButton.Left
: e.Type == RawMouseEventType.RightButtonUp ? MouseButton.Right : MouseButton.Middle,
e.InputModifiers);
break;
case RawMouseEventType.Move:
- MouseMove(mouse, e.Root, e.Position, e.InputModifiers);
+ e.Handled = MouseMove(mouse, e.Root, e.Position, e.InputModifiers);
break;
case RawMouseEventType.Wheel:
- MouseWheel(mouse, e.Root, e.Position, ((RawMouseWheelEventArgs)e).Delta, e.InputModifiers);
+ e.Handled = MouseWheel(mouse, e.Root, e.Position, ((RawMouseWheelEventArgs)e).Delta, e.InputModifiers);
break;
}
}
@@ -144,7 +144,7 @@ namespace Perspex.Input
ClearPointerOver(this, root);
}
- private void MouseDown(IMouseDevice device, uint timestamp, IInputElement root, Point p, MouseButton button, InputModifiers inputModifiers)
+ private bool MouseDown(IMouseDevice device, uint timestamp, IInputElement root, Point p, MouseButton button, InputModifiers inputModifiers)
{
var hit = HitTest(root, p);
@@ -167,7 +167,7 @@ namespace Perspex.Input
_lastClickRect = new Rect(p, new Size())
.Inflate(new Thickness(settings.DoubleClickSize.Width / 2, settings.DoubleClickSize.Height / 2));
- var e = new PointerPressEventArgs
+ var e = new PointerPressedEventArgs
{
Device = this,
RoutedEvent = InputElement.PointerPressedEvent,
@@ -178,11 +178,14 @@ namespace Perspex.Input
};
source.RaiseEvent(e);
+ return e.Handled;
}
}
+
+ return false;
}
- private void MouseMove(IMouseDevice device, IInputRoot root, Point p, InputModifiers inputModifiers)
+ private bool MouseMove(IMouseDevice device, IInputRoot root, Point p, InputModifiers inputModifiers)
{
IInputElement source;
@@ -197,51 +200,62 @@ namespace Perspex.Input
source = Captured;
}
- source.RaiseEvent(new PointerEventArgs
+ var e = new PointerEventArgs
{
Device = this,
RoutedEvent = InputElement.PointerMovedEvent,
Source = source,
InputModifiers = inputModifiers
- });
+ };
+
+ source.RaiseEvent(e);
+ return e.Handled;
}
- private void MouseUp(IMouseDevice device, IInputRoot root, Point p, MouseButton button, InputModifiers inputModifiers)
+ private bool MouseUp(IMouseDevice device, IInputRoot root, Point p, MouseButton button, InputModifiers inputModifiers)
{
var hit = HitTest(root, p);
if (hit != null)
{
- IInteractive source = GetSource(hit);
-
- source?.RaiseEvent(new PointerReleasedEventArgs
+ var source = GetSource(hit);
+ var e = new PointerReleasedEventArgs
{
Device = this,
RoutedEvent = InputElement.PointerReleasedEvent,
Source = source,
MouseButton = button,
InputModifiers = inputModifiers
- });
+ };
+
+ source?.RaiseEvent(e);
+ return e.Handled;
}
+
+ return false;
}
- private void MouseWheel(IMouseDevice device, IInputRoot root, Point p, Vector delta, InputModifiers inputModifiers)
+ private bool MouseWheel(IMouseDevice device, IInputRoot root, Point p, Vector delta, InputModifiers inputModifiers)
{
var hit = HitTest(root, p);
if (hit != null)
{
- IInteractive source = GetSource(hit);
-
- source?.RaiseEvent(new PointerWheelEventArgs
+ var source = GetSource(hit);
+ var e = new PointerWheelEventArgs
{
Device = this,
RoutedEvent = InputElement.PointerWheelChangedEvent,
Source = source,
Delta = delta,
InputModifiers = inputModifiers
- });
+ };
+
+ source?.RaiseEvent(e);
+ return e.Handled;
}
+
+ return false;
}
private IInteractive GetSource(IVisual hit)
diff --git a/src/Perspex.Input/PointerEventArgs.cs b/src/Perspex.Input/PointerEventArgs.cs
index e2196411a6..fab4c2a9c6 100644
--- a/src/Perspex.Input/PointerEventArgs.cs
+++ b/src/Perspex.Input/PointerEventArgs.cs
@@ -26,7 +26,7 @@ namespace Perspex.Input
Middle
}
- public class PointerPressEventArgs : PointerEventArgs
+ public class PointerPressedEventArgs : PointerEventArgs
{
public int ClickCount { get; set; }
public MouseButton MouseButton { get; set; }
diff --git a/src/Perspex.Input/Raw/RawInputEventArgs.cs b/src/Perspex.Input/Raw/RawInputEventArgs.cs
index 7708165a14..4918710c46 100644
--- a/src/Perspex.Input/Raw/RawInputEventArgs.cs
+++ b/src/Perspex.Input/Raw/RawInputEventArgs.cs
@@ -16,7 +16,7 @@ namespace Perspex.Input.Raw
}
public IInputDevice Device { get; private set; }
-
+ public bool Handled { get; set; }
public uint Timestamp { get; private set; }
}
}
diff --git a/src/Perspex.SceneGraph/Media/FormattedText.cs b/src/Perspex.SceneGraph/Media/FormattedText.cs
index 25ef16cd7e..e2db938612 100644
--- a/src/Perspex.SceneGraph/Media/FormattedText.cs
+++ b/src/Perspex.SceneGraph/Media/FormattedText.cs
@@ -42,6 +42,11 @@ namespace Perspex.Media
var platform = PerspexLocator.Current.GetService();
+ if (platform == null)
+ {
+ throw new Exception("Could not create FormattedText: IPlatformRenderInterface not registered.");
+ }
+
PlatformImpl = platform.CreateFormattedText(
text,
fontFamilyName,
diff --git a/src/Perspex.Themes.Default/TreeViewItem.paml b/src/Perspex.Themes.Default/TreeViewItem.paml
index 5758f598bb..9df1ec1545 100644
--- a/src/Perspex.Themes.Default/TreeViewItem.paml
+++ b/src/Perspex.Themes.Default/TreeViewItem.paml
@@ -11,18 +11,12 @@
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
+ TemplatedControl.IsTemplateFocusTarget="True"
Grid.Column="1">
-
_settings->Opacity = _opacityStack.Pop();
private Matrix _currentTransform = Matrix.Identity;
- private readonly float[] _fmatrix = new float[6];
+
public Matrix Transform
{
get { return _currentTransform; }
diff --git a/src/Windows/Perspex.Direct2D1/app.config b/src/Windows/Perspex.Direct2D1/app.config
index 2cc3da0dcc..0dfc66e74b 100644
--- a/src/Windows/Perspex.Direct2D1/app.config
+++ b/src/Windows/Perspex.Direct2D1/app.config
@@ -15,8 +15,16 @@
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Windows/Perspex.Win32/WindowImpl.cs b/src/Windows/Perspex.Win32/WindowImpl.cs
index 617f07c30e..35be38c06d 100644
--- a/src/Windows/Perspex.Win32/WindowImpl.cs
+++ b/src/Windows/Perspex.Win32/WindowImpl.cs
@@ -553,10 +553,10 @@ namespace Perspex.Win32
{
Input(e);
- if (msg >= 161 && msg <= 173)
- return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
-
- return IntPtr.Zero;
+ if (e.Handled)
+ {
+ return IntPtr.Zero;
+ }
}
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
diff --git a/tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs b/tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs
index 418c4bd7bc..40f542ae76 100644
--- a/tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs
+++ b/tests/Perspex.Base.UnitTests/PerspexObjectTests_Binding.cs
@@ -262,9 +262,6 @@ namespace Perspex.Base.UnitTests
public static readonly StyledProperty FooProperty =
PerspexProperty.Register("Foo", "foodefault");
- public static readonly StyledProperty BazProperty =
- PerspexProperty.Register("Baz", "bazdefault", true);
-
public static readonly StyledProperty QuxProperty =
PerspexProperty.Register("Qux", 5.6);
}
diff --git a/tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs b/tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs
index c3ff947a4d..316971c7de 100644
--- a/tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs
+++ b/tests/Perspex.Base.UnitTests/PerspexObjectTests_Metadata.cs
@@ -51,24 +51,12 @@ namespace Perspex.Base.UnitTests
{
public static readonly StyledProperty FooProperty =
PerspexProperty.Register("Foo");
-
- public static readonly StyledProperty BazProperty =
- PerspexProperty.Register("Baz");
-
- public static readonly StyledProperty QuxProperty =
- PerspexProperty.Register("Qux");
}
private class Class2 : Class1
{
public static readonly StyledProperty BarProperty =
PerspexProperty.Register("Bar");
-
- public static readonly StyledProperty FlobProperty =
- PerspexProperty.Register("Flob");
-
- public static readonly StyledProperty FredProperty =
- PerspexProperty.Register("Fred");
}
private class AttachedOwner
diff --git a/tests/Perspex.Base.UnitTests/StyledPropertyTests.cs b/tests/Perspex.Base.UnitTests/StyledPropertyTests.cs
index 6685a08059..9da28bd023 100644
--- a/tests/Perspex.Base.UnitTests/StyledPropertyTests.cs
+++ b/tests/Perspex.Base.UnitTests/StyledPropertyTests.cs
@@ -35,8 +35,6 @@ namespace Perspex.Base.UnitTests
private class Class1 : PerspexObject
{
- public static readonly StyledProperty FooProperty =
- PerspexProperty.Register("Foo", "default");
}
private class Class2 : PerspexObject
diff --git a/tests/Perspex.Controls.UnitTests/ContentControlTests.cs b/tests/Perspex.Controls.UnitTests/ContentControlTests.cs
index 979a0b4bab..c3709ed4ff 100644
--- a/tests/Perspex.Controls.UnitTests/ContentControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ContentControlTests.cs
@@ -1,18 +1,15 @@
// 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.Specialized;
using System.Linq;
using Moq;
using Perspex.Controls.Presenters;
using Perspex.Controls.Templates;
using Perspex.LogicalTree;
-using Perspex.Platform;
using Perspex.Styling;
+using Perspex.UnitTests;
using Perspex.VisualTree;
-using Ploeh.AutoFixture;
-using Ploeh.AutoFixture.AutoMoq;
using Xunit;
namespace Perspex.Controls.UnitTests
@@ -22,44 +19,38 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Template_Should_Be_Instantiated()
{
- using (var ctx = RegisterServices())
- {
- var target = new ContentControl();
- target.Content = "Foo";
- target.Template = GetTemplate();
- target.ApplyTemplate();
- ((ContentPresenter)target.Presenter).UpdateChild();
-
- var child = ((IVisual)target).VisualChildren.Single();
- Assert.IsType(child);
- child = child.VisualChildren.Single();
- Assert.IsType(child);
- child = child.VisualChildren.Single();
- Assert.IsType(child);
- }
+ var target = new ContentControl();
+ target.Content = "Foo";
+ target.Template = GetTemplate();
+ target.ApplyTemplate();
+ ((ContentPresenter)target.Presenter).UpdateChild();
+
+ var child = ((IVisual)target).VisualChildren.Single();
+ Assert.IsType(child);
+ child = child.VisualChildren.Single();
+ Assert.IsType(child);
+ child = child.VisualChildren.Single();
+ Assert.IsType(child);
}
[Fact]
public void Templated_Children_Should_Be_Styled()
{
- using (var ctx = RegisterServices())
- {
- var root = new TestRoot();
- var target = new ContentControl();
- var styler = new Mock();
-
- PerspexLocator.CurrentMutable.Bind().ToConstant(styler.Object);
- target.Content = "Foo";
- target.Template = GetTemplate();
- root.Child = target;
-
- target.ApplyTemplate();
-
- styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
- styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
- styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
- styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
- }
+ var root = new TestRoot();
+ var target = new ContentControl();
+ var styler = new Mock();
+
+ PerspexLocator.CurrentMutable.Bind().ToConstant(styler.Object);
+ target.Content = "Foo";
+ target.Template = GetTemplate();
+ root.Child = target;
+
+ target.ApplyTemplate();
+
+ styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
+ styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
+ styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
+ styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
}
[Fact]
@@ -261,15 +252,5 @@ namespace Perspex.Controls.UnitTests
};
});
}
-
- private IDisposable RegisterServices()
- {
- var result = PerspexLocator.EnterScope();
- var fixture = new Fixture().Customize(new AutoMoqCustomization());
- var renderInterface = fixture.Create();
- PerspexLocator.CurrentMutable
- .Bind().ToConstant(renderInterface);
- return result;
- }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/ControlTests.cs b/tests/Perspex.Controls.UnitTests/ControlTests.cs
index 9955b3ed63..a4d7c65a3b 100644
--- a/tests/Perspex.Controls.UnitTests/ControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ControlTests.cs
@@ -5,10 +5,8 @@ using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using Moq;
-using Perspex.Layout;
-using Perspex.Platform;
-using Perspex.Rendering;
using Perspex.Styling;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Controls.UnitTests
@@ -147,44 +145,6 @@ namespace Perspex.Controls.UnitTests
}
}
- private class TestRoot : Decorator, ILayoutRoot, IRenderRoot, IStyleRoot
- {
- public Size ClientSize
- {
- get { throw new NotImplementedException(); }
- }
-
- public Size MaxClientSize
- {
- get { throw new NotImplementedException(); }
- }
-
- public ILayoutManager LayoutManager
- {
- get { throw new NotImplementedException(); }
- }
-
- public IRenderTarget RenderTarget
- {
- get { throw new NotImplementedException(); }
- }
-
- public IRenderQueueManager RenderQueueManager
- {
- get { throw new NotImplementedException(); }
- }
-
- public Point PointToClient(Point p)
- {
- throw new NotImplementedException();
- }
-
- public Point PointToScreen(Point p)
- {
- throw new NotImplementedException();
- }
- }
-
private class TestControl : Control
{
public new PerspexObject InheritanceParent => base.InheritanceParent;
diff --git a/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs b/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs
index b7bb52379b..0941a9ce60 100644
--- a/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs
+++ b/tests/Perspex.Controls.UnitTests/ControlTests_NameScope.cs
@@ -6,6 +6,7 @@ using Perspex.Controls.Presenters;
using Perspex.Controls.Templates;
using Perspex.Rendering;
using Perspex.Styling;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Controls.UnitTests
@@ -17,7 +18,7 @@ namespace Perspex.Controls.UnitTests
{
var root = new TestRoot
{
- Content = new Border
+ Child = new Border
{
Name = "foo",
Child = new Border
@@ -28,10 +29,9 @@ namespace Perspex.Controls.UnitTests
};
root.ApplyTemplate();
- ((ContentPresenter)root.Presenter).UpdateChild();
- Assert.Same(root.Find("foo"), root.Content);
- Assert.Same(root.Find("bar"), ((Border)root.Content).Child);
+ Assert.Same(root.FindControl("foo"), root.Child);
+ Assert.Same(root.FindControl("bar"), ((Border)root.Child).Child);
}
[Fact]
@@ -39,7 +39,7 @@ namespace Perspex.Controls.UnitTests
{
var root = new TestRoot
{
- Content = new Border
+ Child = new Border
{
Name = "foo",
Child = new Border
@@ -49,18 +49,16 @@ namespace Perspex.Controls.UnitTests
}
};
- root.ApplyTemplate();
- root.Content = null;
- root.Presenter.ApplyTemplate();
+ root.Child = null;
- Assert.Null(root.Find("foo"));
- Assert.Null(root.Find("bar"));
+ Assert.Null(root.FindControl("foo"));
+ Assert.Null(root.FindControl("bar"));
}
[Fact]
public void Control_Should_Not_Register_With_Template_NameScope()
{
- var root = new TestRoot
+ var root = new TestTemplatedRoot
{
Content = new Border
{
@@ -72,61 +70,5 @@ namespace Perspex.Controls.UnitTests
Assert.Null(NameScope.GetNameScope((Control)root.Presenter).Find("foo"));
}
-
- private class TestRoot : ContentControl, IRenderRoot, INameScope, IStyleRoot
- {
- private readonly NameScope _nameScope = new NameScope();
-
- public TestRoot()
- {
- Template = new FuncControlTemplate(x => new ContentPresenter
- {
- Name = "PART_ContentPresenter",
- [!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty],
- });
- }
-
- public event EventHandler Registered
- {
- add { _nameScope.Registered += value; }
- remove { _nameScope.Registered -= value; }
- }
-
- public event EventHandler Unregistered
- {
- add { _nameScope.Unregistered += value; }
- remove { _nameScope.Unregistered -= value; }
- }
-
- public IRenderQueueManager RenderQueueManager
- {
- get { throw new NotImplementedException(); }
- }
-
- public Point PointToClient(Point p)
- {
- throw new NotImplementedException();
- }
-
- public Point PointToScreen(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);
- }
- }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/DropDownTests.cs b/tests/Perspex.Controls.UnitTests/DropDownTests.cs
index 9c219ea34b..0ee59a9a87 100644
--- a/tests/Perspex.Controls.UnitTests/DropDownTests.cs
+++ b/tests/Perspex.Controls.UnitTests/DropDownTests.cs
@@ -41,15 +41,5 @@ namespace Perspex.Controls.UnitTests
};
});
}
-
- private IDisposable RegisterServices()
- {
- var result = PerspexLocator.EnterScope();
- var fixture = new Fixture().Customize(new AutoMoqCustomization());
- var renderInterface = fixture.Create();
- PerspexLocator.CurrentMutable.Bind().ToConstant(renderInterface);
-
- return result;
- }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/GridSplitterTests.cs b/tests/Perspex.Controls.UnitTests/GridSplitterTests.cs
index 5fa3e4294d..9ab985bf1d 100644
--- a/tests/Perspex.Controls.UnitTests/GridSplitterTests.cs
+++ b/tests/Perspex.Controls.UnitTests/GridSplitterTests.cs
@@ -3,7 +3,7 @@
using Perspex.Controls.Primitives;
using Perspex.Input;
using Perspex.Platform;
-
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Controls.UnitTests
diff --git a/tests/Perspex.Controls.UnitTests/ListBoxTests.cs b/tests/Perspex.Controls.UnitTests/ListBoxTests.cs
index fd58322b02..a502d3b186 100644
--- a/tests/Perspex.Controls.UnitTests/ListBoxTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ListBoxTests.cs
@@ -115,7 +115,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
- target.Presenter.Panel.Children[1].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[1].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
diff --git a/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs b/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs
index 47547837f9..76f866c3c6 100644
--- a/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs
+++ b/tests/Perspex.Controls.UnitTests/ListBoxTests_Single.cs
@@ -65,7 +65,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
- target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
@@ -86,7 +86,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
target.SelectedIndex = 0;
- target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
@@ -107,7 +107,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
- target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
@@ -129,7 +129,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
target.SelectedIndex = 0;
- target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
@@ -151,7 +151,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
target.SelectedIndex = 0;
- target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
@@ -173,7 +173,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplate(target);
target.SelectedIndex = 1;
- target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressEventArgs
+ target.Presenter.Panel.Children[0].RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
@@ -236,15 +236,5 @@ namespace Perspex.Controls.UnitTests
// Now the ItemsPresenter should be reigstered, so apply its template.
target.Presenter.ApplyTemplate();
}
-
- private class Item
- {
- public Item(string value)
- {
- Value = value;
- }
-
- public string Value { get; }
- }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/PanelTests.cs b/tests/Perspex.Controls.UnitTests/PanelTests.cs
index 68f6075e2e..34a052645e 100644
--- a/tests/Perspex.Controls.UnitTests/PanelTests.cs
+++ b/tests/Perspex.Controls.UnitTests/PanelTests.cs
@@ -117,10 +117,5 @@ namespace Perspex.Controls.UnitTests
Assert.Equal(new Control[0], panel.Children);
Assert.Equal(new ILogical[0], panel.GetLogicalChildren());
}
-
- private class TestReparent : Panel
- {
- public new IPerspexList LogicalChildren => base.LogicalChildren;
- }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj b/tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
index 23415fb0b4..5704139a50 100644
--- a/tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
+++ b/tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
@@ -137,7 +137,6 @@
-
@@ -151,6 +150,10 @@
{D211E587-D8BC-45B9-95A4-F297C8FA5200}
Perspex.Animation
+
+ {799a7bb5-3c2c-48b6-85a7-406a12c420da}
+ Perspex.Application
+
{B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
@@ -179,6 +182,10 @@
{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
+
+ {88060192-33d5-4932-b0f9-8bd2763e857d}
+ Perspex.UnitTests
+
@@ -187,6 +194,9 @@
+
+
+
diff --git a/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs b/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
index b8beafa0c4..42a490b38a 100644
--- a/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
+++ b/tests/Perspex.Controls.UnitTests/Presenters/ContentPresenterTests.cs
@@ -6,6 +6,7 @@ using Moq;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
+using Perspex.UnitTests;
using Perspex.VisualTree;
using Xunit;
diff --git a/tests/Perspex.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Perspex.Controls.UnitTests/Primitives/PopupTests.cs
index 4751ffbfde..0354cd6e61 100644
--- a/tests/Perspex.Controls.UnitTests/Primitives/PopupTests.cs
+++ b/tests/Perspex.Controls.UnitTests/Primitives/PopupTests.cs
@@ -12,6 +12,7 @@ using Perspex.Layout;
using Perspex.LogicalTree;
using Perspex.Platform;
using Perspex.Styling;
+using Perspex.UnitTests;
using Perspex.VisualTree;
using Xunit;
diff --git a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs
index 22f2509e1d..881c436d1d 100644
--- a/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs
+++ b/tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs
@@ -100,10 +100,5 @@ namespace Perspex.Controls.UnitTests.Primitives
SelectionModeProperty.OverrideDefaultValue(SelectionMode.AlwaysSelected);
}
}
-
- private class Item : Control, ISelectable
- {
- public bool IsSelected { get; set; }
- }
}
}
diff --git a/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs b/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs
index 071ba550b0..4de5d8fd3b 100644
--- a/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/Primitives/TemplatedControlTests.cs
@@ -10,6 +10,7 @@ using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.LogicalTree;
using Perspex.Styling;
+using Perspex.UnitTests;
using Perspex.VisualTree;
using Xunit;
@@ -176,12 +177,8 @@ namespace Perspex.Controls.UnitTests.Primitives
[Fact]
public void Templated_Children_Should_Be_Styled()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.MockStyler))
{
- var styler = new Mock();
-
- PerspexLocator.CurrentMutable.Bind().ToConstant(styler.Object);
-
TestTemplatedControl target;
var root = new TestRoot
@@ -205,6 +202,7 @@ namespace Perspex.Controls.UnitTests.Primitives
target.ApplyTemplate();
+ var styler = Mock.Get(UnitTestApplication.Current.Services.Styler);
styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once());
@@ -330,23 +328,6 @@ namespace Perspex.Controls.UnitTests.Primitives
};
}
- private static IControl ItemsControlTemplate(ItemsControl control)
- {
- return new Border
- {
- Child = new ScrollViewer
- {
- Template = new FuncControlTemplate(ScrollViewerTemplate),
- Content = new ItemsPresenter
- {
- Name = "PART_ItemsPresenter",
- [!ItemsPresenter.ItemsProperty] = control[!ItemsControl.ItemsProperty],
- [!ItemsPresenter.ItemsPanelProperty] = control[!ItemsControl.ItemsPanelProperty],
- }
- }
- };
- }
-
private static Control ScrollViewerTemplate(ScrollViewer control)
{
var result = new ScrollContentPresenter
@@ -357,16 +338,5 @@ namespace Perspex.Controls.UnitTests.Primitives
return result;
}
-
- private class ApplyTemplateTracker : Control
- {
- public List> Invocations { get; } = new List>();
-
- public override void ApplyTemplate()
- {
- base.ApplyTemplate();
- Invocations.Add(Tuple.Create(this.GetVisualParent(), this.GetLogicalParent()));
- }
- }
}
}
\ No newline at end of file
diff --git a/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs b/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs
index dba82f976e..26136a84d8 100644
--- a/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs
+++ b/tests/Perspex.Controls.UnitTests/ScrollViewerTests.cs
@@ -84,17 +84,5 @@ namespace Perspex.Controls.UnitTests
},
};
}
-
- private Control CreateNestedTemplate(ContentControl control)
- {
- return new ScrollViewer
- {
- Template = new FuncControlTemplate(CreateTemplate),
- Content = new ContentPresenter
- {
- Name = "PART_ContentPresenter",
- }
- };
- }
}
}
\ No newline at end of file
diff --git a/tests/Perspex.Controls.UnitTests/TabControlTests.cs b/tests/Perspex.Controls.UnitTests/TabControlTests.cs
index 5e0255525c..0f8568b25d 100644
--- a/tests/Perspex.Controls.UnitTests/TabControlTests.cs
+++ b/tests/Perspex.Controls.UnitTests/TabControlTests.cs
@@ -9,6 +9,7 @@ using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.LogicalTree;
using Perspex.Styling;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Controls.UnitTests
@@ -130,10 +131,8 @@ namespace Perspex.Controls.UnitTests
var template = new FuncControlTemplate(x => new Decorator());
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.RealStyler))
{
- PerspexLocator.CurrentMutable.Bind().ToConstant(new Styler());
-
var root = new TestRoot
{
Styles = new Styles
diff --git a/tests/Perspex.Controls.UnitTests/TestRoot.cs b/tests/Perspex.Controls.UnitTests/TestRoot.cs
deleted file mode 100644
index 416197258b..0000000000
--- a/tests/Perspex.Controls.UnitTests/TestRoot.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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 Moq;
-using Perspex.Layout;
-using Perspex.Platform;
-using Perspex.Rendering;
-using Perspex.Styling;
-
-namespace Perspex.Controls.UnitTests
-{
- internal class TestRoot : Decorator, ILayoutRoot, IRenderRoot, IStyleRoot
- {
- public Size ClientSize => new Size(100, 100);
-
- public Size MaxClientSize => Size.Infinity;
-
- public ILayoutManager LayoutManager => new Mock().Object;
-
- public IRenderTarget RenderTarget
- {
- get { throw new NotImplementedException(); }
- }
-
- public IRenderQueueManager RenderQueueManager => null;
-
- public Point PointToClient(Point p)
- {
- throw new NotImplementedException();
- }
-
- public Point PointToScreen(Point p)
- {
- return new Point();
- }
- }
-}
diff --git a/tests/Perspex.Controls.UnitTests/TopLevelTests.cs b/tests/Perspex.Controls.UnitTests/TopLevelTests.cs
index 9999630b85..6a6769d4c1 100644
--- a/tests/Perspex.Controls.UnitTests/TopLevelTests.cs
+++ b/tests/Perspex.Controls.UnitTests/TopLevelTests.cs
@@ -13,6 +13,7 @@ using Perspex.Layout;
using Perspex.Platform;
using Perspex.Rendering;
using Perspex.Styling;
+using Perspex.UnitTests;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Xunit;
@@ -24,10 +25,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void ClientSize_Should_Be_Set_On_Construction()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
@@ -40,10 +39,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Width_Should_Not_Be_Set_On_Construction()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
@@ -56,10 +53,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Height_Should_Not_Be_Set_On_Construction()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
@@ -72,10 +67,10 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Layout_Pass_Should_Not_Be_Automatically_Scheduled()
{
- using (PerspexLocator.EnterScope())
- {
- RegisterServices();
+ var services = TestServices.StyledWindow.With(layoutManager: Mock.Of());
+ using (UnitTestApplication.Start(services))
+ {
var impl = new Mock();
var target = new TestTopLevel(impl.Object);
@@ -88,11 +83,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Bounds_Should_Be_Set_After_Layout_Pass()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
- PerspexLocator.CurrentMutable.Bind().ToConstant(new LayoutManager());
-
var impl = new Mock();
impl.SetupProperty(x => x.ClientSize);
impl.SetupProperty(x => x.Resized);
@@ -116,11 +108,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Impl_ClientSize_Should_Be_Set_After_Layout_Pass()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
- PerspexLocator.CurrentMutable.Bind().ToConstant(new LayoutManager());
-
var impl = new Mock();
var target = new TestTopLevel(impl.Object)
@@ -142,10 +131,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Width_And_Height_Should_Not_Be_Set_After_Layout_Pass()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
@@ -160,10 +147,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Width_And_Height_Should_Be_Set_After_Window_Resize_Notification()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.SetupAllProperties();
impl.Setup(x => x.ClientSize).Returns(new Size(123, 456));
@@ -180,10 +165,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Activate_Should_Call_Impl_Activate()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
var target = new TestTopLevel(impl.Object);
@@ -196,10 +179,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Impl_Activate_Should_Call_Raise_Activated_Event()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.SetupAllProperties();
@@ -216,10 +197,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Impl_Close_Should_Call_Raise_Closed_Event()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.SetupAllProperties();
@@ -236,10 +215,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Impl_Deactivate_Should_Call_Raise_Activated_Event()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.SetupAllProperties();
@@ -256,12 +233,14 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Impl_Input_Should_Pass_Input_To_InputManager()
{
- using (PerspexLocator.EnterScope())
- {
- RegisterServices();
+ var inputManagerMock = new Mock();
+ var services = TestServices.StyledWindow.With(inputManager: inputManagerMock.Object);
+ using (UnitTestApplication.Start(services))
+ {
var impl = new Mock();
impl.SetupAllProperties();
+
var target = new TestTopLevel(impl.Object);
var input = new RawKeyEventArgs(
@@ -271,7 +250,6 @@ namespace Perspex.Controls.UnitTests
Key.A, InputModifiers.None);
impl.Object.Input(input);
- var inputManagerMock = Mock.Get(InputManager.Instance);
inputManagerMock.Verify(x => x.Process(input));
}
}
@@ -279,10 +257,8 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Adding_Top_Level_As_Child_Should_Throw_Exception()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- RegisterServices();
-
var impl = new Mock();
impl.SetupAllProperties();
var target = new TestTopLevel(impl.Object);
@@ -305,31 +281,6 @@ namespace Perspex.Controls.UnitTests
});
}
- private void RegisterServices()
- {
- var fixture = new Fixture().Customize(new AutoMoqCustomization());
- var l = PerspexLocator.CurrentMutable;
-
- var formattedText = fixture.Create();
- var globalStyles = new Mock();
- var layoutManager = fixture.Create();
- var renderInterface = fixture.Create();
- var renderManager = fixture.Create();
- var windowImpl = new Mock();
- var theme = new Styles();
-
- globalStyles.Setup(x => x.Styles).Returns(theme);
-
- PerspexLocator.CurrentMutable
- .Bind().ToConstant(new Mock().Object)
- .Bind().ToConstant(new Mock().Object)
- .Bind().ToConstant(globalStyles.Object)
- .Bind().ToConstant(layoutManager)
- .Bind().ToConstant(renderInterface)
- .Bind().ToConstant(renderManager)
- .Bind().ToConstant(new Styler());
- }
-
private class TestTopLevel : TopLevel
{
public TestTopLevel(ITopLevelImpl impl)
diff --git a/tests/Perspex.Controls.UnitTests/TreeViewTests.cs b/tests/Perspex.Controls.UnitTests/TreeViewTests.cs
index f28cabe0f3..4d9aa925ec 100644
--- a/tests/Perspex.Controls.UnitTests/TreeViewTests.cs
+++ b/tests/Perspex.Controls.UnitTests/TreeViewTests.cs
@@ -8,6 +8,7 @@ using Perspex.Controls.Presenters;
using Perspex.Controls.Templates;
using Perspex.Input;
using Perspex.LogicalTree;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Controls.UnitTests
@@ -97,7 +98,7 @@ namespace Perspex.Controls.UnitTests
Assert.NotNull(container);
- container.RaiseEvent(new PointerPressEventArgs
+ container.RaiseEvent(new PointerPressedEventArgs
{
RoutedEvent = InputElement.PointerPressedEvent,
MouseButton = MouseButton.Left,
diff --git a/tests/Perspex.LeakTests/ControlTests.cs b/tests/Perspex.LeakTests/ControlTests.cs
index 7ad6c19099..7d34613c86 100644
--- a/tests/Perspex.LeakTests/ControlTests.cs
+++ b/tests/Perspex.LeakTests/ControlTests.cs
@@ -9,6 +9,7 @@ using Perspex.Controls;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.Layout;
+using Perspex.UnitTests;
using Perspex.VisualTree;
using Xunit;
using Xunit.Abstractions;
@@ -20,282 +21,305 @@ namespace Perspex.LeakTests
{
public ControlTests(ITestOutputHelper atr)
{
- TestApp.Initialize();
DotMemoryUnitTestOutput.SetOutputMethod(atr.WriteLine);
}
[Fact]
public void Canvas_Is_Freed()
{
- Func run = () =>
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
{
- var window = new Window
+ Func run = () =>
{
- Content = new Canvas()
- };
+ var window = new Window
+ {
+ Content = new Canvas()
+ };
- // Do a layout and make sure that Canvas gets added to visual tree.
- LayoutManager.Instance.ExecuteInitialLayoutPass(window);
- Assert.IsType
+
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs b/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs
index a496f26fc5..4c6783c0e0 100644
--- a/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs
+++ b/tests/Perspex.Markup.Xaml.UnitTests/StyleTests.cs
@@ -3,13 +3,11 @@
using System.Linq;
using System.Reactive.Linq;
-using Moq;
using Perspex.Controls;
-using Perspex.Controls.Primitives;
using Perspex.Data;
using Perspex.Markup.Xaml.Data;
-using Perspex.Platform;
using Perspex.Styling;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Markup.Xaml.UnitTests
@@ -19,12 +17,8 @@ namespace Perspex.Markup.Xaml.UnitTests
[Fact]
public void Binding_Should_Be_Assigned_To_Setter_Value_Instead_Of_Bound()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
{
- PerspexLocator.CurrentMutable
- .Bind()
- .ToConstant(Mock.Of());
-
var xaml = "";
var loader = new PerspexXamlLoader();
var style = (Style)loader.Load(xaml);
@@ -37,13 +31,8 @@ namespace Perspex.Markup.Xaml.UnitTests
[Fact]
public void Setter_With_TwoWay_Binding_Should_Update_Source()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.MockThreadingInterface))
{
- PerspexLocator.CurrentMutable
- .Bind()
- .ToConstant(Mock.Of(x =>
- x.CurrentThreadIsLoopThread == true));
-
var data = new Data
{
Foo = "foo",
@@ -75,13 +64,8 @@ namespace Perspex.Markup.Xaml.UnitTests
[Fact]
public void Setter_With_TwoWay_Binding_And_Activator_Should_Update_Source()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.MockThreadingInterface))
{
- PerspexLocator.CurrentMutable
- .Bind()
- .ToConstant(Mock.Of(x =>
- x.CurrentThreadIsLoopThread == true));
-
var data = new Data
{
Foo = "foo",
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/Templates/TreeDataTemplateTests.cs b/tests/Perspex.Markup.Xaml.UnitTests/Templates/TreeDataTemplateTests.cs
index 5bf4cea9eb..74bc5db4ed 100644
--- a/tests/Perspex.Markup.Xaml.UnitTests/Templates/TreeDataTemplateTests.cs
+++ b/tests/Perspex.Markup.Xaml.UnitTests/Templates/TreeDataTemplateTests.cs
@@ -2,11 +2,10 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Linq;
-using Moq;
using Perspex.Controls.Templates;
using Perspex.Markup.Xaml.Data;
using Perspex.Markup.Xaml.Templates;
-using Perspex.Platform;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Markup.Xaml.UnitTests
@@ -16,12 +15,8 @@ namespace Perspex.Markup.Xaml.UnitTests
[Fact]
public void Binding_Should_Be_Assigned_To_ItemsSource_Instead_Of_Bound()
{
- using (PerspexLocator.EnterScope())
+ using (UnitTestApplication.Start(TestServices.MockPlatformWrapper))
{
- PerspexLocator.CurrentMutable
- .Bind()
- .ToConstant(Mock.Of());
-
var xaml = "";
var loader = new PerspexXamlLoader();
var templates = (DataTemplates)loader.Load(xaml);
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/TestRoot.cs b/tests/Perspex.Markup.Xaml.UnitTests/TestRoot.cs
deleted file mode 100644
index 5cc71ef9d9..0000000000
--- a/tests/Perspex.Markup.Xaml.UnitTests/TestRoot.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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;
-using Perspex.Styling;
-
-namespace Perspex.Markup.Xaml.UnitTests
-{
- public class TestRoot : Decorator, IRenderRoot, INameScope, IStyleRoot
- {
- private readonly NameScope _nameScope = new NameScope();
-
- event EventHandler INameScope.Registered
- {
- add { _nameScope.Registered += value; ++NameScopeRegisteredSubscribers; }
- remove { _nameScope.Registered -= value; --NameScopeRegisteredSubscribers; }
- }
-
- public event EventHandler 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 PointToClient(Point p)
- {
- throw new NotImplementedException();
- }
-
- public Point PointToScreen(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);
- }
- }
-}
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/app.config b/tests/Perspex.Markup.Xaml.UnitTests/app.config
new file mode 100644
index 0000000000..fa66e8c206
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Perspex.RenderTests/app.config b/tests/Perspex.RenderTests/app.config
index 369fc74fc1..6d348f8066 100644
--- a/tests/Perspex.RenderTests/app.config
+++ b/tests/Perspex.RenderTests/app.config
@@ -15,8 +15,16 @@
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Perspex.Styling.UnitTests/ActivatedSubjectTests.cs b/tests/Perspex.Styling.UnitTests/ActivatedSubjectTests.cs
index 0e3947c5d9..0599430894 100644
--- a/tests/Perspex.Styling.UnitTests/ActivatedSubjectTests.cs
+++ b/tests/Perspex.Styling.UnitTests/ActivatedSubjectTests.cs
@@ -53,18 +53,6 @@ namespace Perspex.Styling.UnitTests
Assert.NotNull(source.Error);
}
- private class Class1 : PerspexObject
- {
- public static readonly StyledProperty FooProperty =
- PerspexProperty.Register("Foo", "foodefault");
-
- public string Foo
- {
- get { return GetValue(FooProperty); }
- set { SetValue(FooProperty, value); }
- }
- }
-
private class TestSubject : ISubject
diff --git a/tests/Perspex.Styling.UnitTests/StyleActivatorTests.cs b/tests/Perspex.Styling.UnitTests/StyleActivatorTests.cs
index afd573dd9d..d78c71caa0 100644
--- a/tests/Perspex.Styling.UnitTests/StyleActivatorTests.cs
+++ b/tests/Perspex.Styling.UnitTests/StyleActivatorTests.cs
@@ -165,18 +165,5 @@ namespace Perspex.Styling.UnitTests
Assert.True(completed);
}
-
- private Recorded>[] OnNextValues(params bool[] values)
- {
- var result = new List>>();
- var time = 1;
-
- foreach (var value in values)
- {
- result.Add(new Recorded>(time, Notification.CreateOnNext(value)));
- }
-
- return result.ToArray();
- }
}
}
diff --git a/tests/Perspex.Styling.UnitTests/StyleTests.cs b/tests/Perspex.Styling.UnitTests/StyleTests.cs
index 1b7455d19d..d3c9bf4447 100644
--- a/tests/Perspex.Styling.UnitTests/StyleTests.cs
+++ b/tests/Perspex.Styling.UnitTests/StyleTests.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Reactive.Subjects;
using Perspex.Controls;
+using Perspex.UnitTests;
using Xunit;
namespace Perspex.Styling.UnitTests
diff --git a/tests/Perspex.Styling.UnitTests/TestRoot.cs b/tests/Perspex.Styling.UnitTests/TestRoot.cs
deleted file mode 100644
index ce46cd06f7..0000000000
--- a/tests/Perspex.Styling.UnitTests/TestRoot.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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 Moq;
-using Perspex.Controls;
-using Perspex.Layout;
-using Perspex.Platform;
-using Perspex.Rendering;
-
-namespace Perspex.Styling.UnitTests
-{
- internal class TestRoot : Decorator, ILayoutRoot, IRenderRoot, IStyleRoot
- {
- public Size ClientSize => new Size(100, 100);
-
- public Size MaxClientSize => Size.Infinity;
-
- public IRenderTarget RenderTarget
- {
- get { throw new NotImplementedException(); }
- }
-
- public IRenderQueueManager RenderQueueManager
- {
- get { throw new NotImplementedException(); }
- }
-
- public Point PointToClient(Point p)
- {
- throw new NotImplementedException();
- }
-
- public Point PointToScreen(Point p)
- {
- return new Point();
- }
- }
-}
diff --git a/tests/Perspex.UnitTests/MockWindowingPlatform.cs b/tests/Perspex.UnitTests/MockWindowingPlatform.cs
new file mode 100644
index 0000000000..9f1f8c9c6b
--- /dev/null
+++ b/tests/Perspex.UnitTests/MockWindowingPlatform.cs
@@ -0,0 +1,30 @@
+using System;
+using Moq;
+using Perspex.Platform;
+
+namespace Perspex.UnitTests
+{
+ public class MockWindowingPlatform : IWindowingPlatform
+ {
+ private readonly Func _windowImpl;
+ private readonly Func _popupImpl;
+
+ public MockWindowingPlatform(Func windowImpl = null, Func popupImpl = null )
+ {
+ _windowImpl = windowImpl;
+ _popupImpl = popupImpl;
+ }
+
+ public IWindowImpl CreateWindow()
+ {
+ return _windowImpl?.Invoke() ?? Mock.Of();
+ }
+
+ public IWindowImpl CreateEmbeddableWindow()
+ {
+ throw new NotImplementedException();
+ }
+
+ public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of();
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.UnitTests/Perspex.UnitTests.csproj b/tests/Perspex.UnitTests/Perspex.UnitTests.csproj
new file mode 100644
index 0000000000..280f7fbba1
--- /dev/null
+++ b/tests/Perspex.UnitTests/Perspex.UnitTests.csproj
@@ -0,0 +1,143 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {88060192-33D5-4932-B0F9-8BD2763E857D}
+ {88060192-33D5-4932-B0F9-8BD2763E857D}
+ Library
+ Properties
+ Perspex.UnitTests
+ Perspex.UnitTests
+ v4.5
+ 512
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll
+ True
+
+
+ ..\..\packages\AutoFixture.3.40.0\lib\net40\Ploeh.AutoFixture.dll
+ True
+
+
+ ..\..\packages\AutoFixture.AutoMoq.3.40.0\lib\net40\Ploeh.AutoFixture.AutoMoq.dll
+ True
+
+
+
+
+ ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
+ True
+
+
+ ..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
+ True
+
+
+ ..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
+ True
+
+
+ ..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {3e53a01a-b331-47f3-b828-4a5717e77a24}
+ Perspex.Markup.Xaml
+
+
+ {6417e941-21bc-467b-a771-0de389353ce6}
+ Perspex.Markup
+
+
+ {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+ Perspex.Animation
+
+
+ {799a7bb5-3c2c-48b6-85a7-406a12c420da}
+ Perspex.Application
+
+
+ {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ Perspex.Base
+
+
+ {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ Perspex.Controls
+
+
+ {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ Perspex.Input
+
+
+ {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ Perspex.Interactivity
+
+
+ {42472427-4774-4c81-8aff-9f27b8e31721}
+ Perspex.Layout
+
+
+ {eb582467-6abb-43a1-b052-e981ba910e3a}
+ Perspex.SceneGraph
+
+
+ {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ Perspex.Styling
+
+
+ {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
+ Perspex.Themes.Default
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Perspex.UnitTests/Properties/AssemblyInfo.cs b/tests/Perspex.UnitTests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..f357370f9b
--- /dev/null
+++ b/tests/Perspex.UnitTests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Perspex.UnitTests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Perspex.UnitTests")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("88060192-33d5-4932-b0f9-8bd2763e857d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tests/Perspex.Markup.UnitTests/TestRoot.cs b/tests/Perspex.UnitTests/TestRoot.cs
similarity index 63%
rename from tests/Perspex.Markup.UnitTests/TestRoot.cs
rename to tests/Perspex.UnitTests/TestRoot.cs
index ecd17dc0c7..3e41c4cfd6 100644
--- a/tests/Perspex.Markup.UnitTests/TestRoot.cs
+++ b/tests/Perspex.UnitTests/TestRoot.cs
@@ -3,13 +3,14 @@
using System;
using Perspex.Controls;
+using Perspex.Layout;
using Perspex.Platform;
using Perspex.Rendering;
using Perspex.Styling;
-namespace Perspex.Markup.UnitTests
+namespace Perspex.UnitTests
{
- public class TestRoot : Decorator, IRenderRoot, INameScope, IStyleRoot
+ public class TestRoot : Decorator, ILayoutRoot, INameScope, IRenderRoot, IStyleRoot
{
private readonly NameScope _nameScope = new NameScope();
@@ -29,37 +30,31 @@ namespace Perspex.Markup.UnitTests
public int NameScopeUnregisteredSubscribers { get; private set; }
- public IRenderTarget RenderTarget
- {
- get { throw new NotImplementedException(); }
- }
+ public Size ClientSize => new Size(100, 100);
- public IRenderQueueManager RenderQueueManager
- {
- get { throw new NotImplementedException(); }
- }
+ public Size MaxClientSize => Size.Infinity;
- public Point PointToClient(Point p)
- {
- throw new NotImplementedException();
- }
+ public ILayoutManager LayoutManager => PerspexLocator.Current.GetService();
- public Point PointToScreen(Point p)
- {
- throw new NotImplementedException();
- }
+ public IRenderTarget RenderTarget => null;
+
+ public IRenderQueueManager RenderQueueManager => null;
+
+ public Point PointToClient(Point p) => p;
+
+ public Point PointToScreen(Point p) => p;
- public void Register(string name, object element)
+ void INameScope.Register(string name, object element)
{
_nameScope.Register(name, element);
}
- public object Find(string name)
+ object INameScope.Find(string name)
{
return _nameScope.Find(name);
}
- public void Unregister(string name)
+ void INameScope.Unregister(string name)
{
_nameScope.Unregister(name);
}
diff --git a/tests/Perspex.UnitTests/TestServices.cs b/tests/Perspex.UnitTests/TestServices.cs
new file mode 100644
index 0000000000..8369f8aed0
--- /dev/null
+++ b/tests/Perspex.UnitTests/TestServices.cs
@@ -0,0 +1,110 @@
+// 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.Reflection;
+using Moq;
+using Perspex.Input;
+using Perspex.Layout;
+using Perspex.Platform;
+using Perspex.Shared.PlatformSupport;
+using Perspex.Styling;
+using Perspex.Themes.Default;
+using Ploeh.AutoFixture;
+using Ploeh.AutoFixture.AutoMoq;
+
+namespace Perspex.UnitTests
+{
+ public class TestServices
+ {
+ private static IFixture s_fixture = new Fixture().Customize(new AutoMoqCustomization());
+
+ public static readonly TestServices StyledWindow = new TestServices(
+ assetLoader: new AssetLoader(),
+ layoutManager: new LayoutManager(),
+ platformWrapper: new PclPlatformWrapper(),
+ renderInterface: s_fixture.Create(),
+ standardCursorFactory: Mock.Of(),
+ styler: new Styler(),
+ theme: () => new DefaultTheme(),
+ threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true),
+ windowingPlatform: new MockWindowingPlatform());
+
+ public static readonly TestServices MockPlatformWrapper = new TestServices(
+ platformWrapper: Mock.Of());
+
+ public static readonly TestServices MockStyler = new TestServices(
+ styler: Mock.Of());
+
+ public static readonly TestServices MockThreadingInterface = new TestServices(
+ threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true));
+
+ public static readonly TestServices RealStyler = new TestServices(
+ styler: new Styler());
+
+ public TestServices(
+ IAssetLoader assetLoader = null,
+ IInputManager inputManager = null,
+ ILayoutManager layoutManager = null,
+ IPclPlatformWrapper platformWrapper = null,
+ IPlatformRenderInterface renderInterface = null,
+ IStandardCursorFactory standardCursorFactory = null,
+ IStyler styler = null,
+ Func theme = null,
+ IPlatformThreadingInterface threadingInterface = null,
+ IWindowImpl windowImpl = null,
+ IWindowingPlatform windowingPlatform = null)
+ {
+ AssetLoader = assetLoader;
+ InputManager = inputManager;
+ LayoutManager = layoutManager;
+ PlatformWrapper = platformWrapper;
+ RenderInterface = renderInterface;
+ StandardCursorFactory = standardCursorFactory;
+ Styler = styler;
+ Theme = theme;
+ ThreadingInterface = threadingInterface;
+ WindowImpl = windowImpl;
+ WindowingPlatform = windowingPlatform;
+ }
+
+ public IAssetLoader AssetLoader { get; }
+ public IInputManager InputManager { get; }
+ public ILayoutManager LayoutManager { get; }
+ public IPclPlatformWrapper PlatformWrapper { get; }
+ public IPlatformRenderInterface RenderInterface { get; }
+ public IStandardCursorFactory StandardCursorFactory { get; }
+ public IStyler Styler { get; }
+ public Func Theme { get; }
+ public IPlatformThreadingInterface ThreadingInterface { get; }
+ public IWindowImpl WindowImpl { get; }
+ public IWindowingPlatform WindowingPlatform { get; }
+
+ public TestServices With(
+ IAssetLoader assetLoader = null,
+ IInputManager inputManager = null,
+ ILayoutManager layoutManager = null,
+ IPclPlatformWrapper platformWrapper = null,
+ IPlatformRenderInterface renderInterface = null,
+ IStandardCursorFactory standardCursorFactory = null,
+ IStyler styler = null,
+ Func theme = null,
+ IPlatformThreadingInterface threadingInterface = null,
+ IWindowImpl windowImpl = null,
+ IWindowingPlatform windowingPlatform = null)
+ {
+ return new TestServices(
+ assetLoader: assetLoader ?? AssetLoader,
+ inputManager: inputManager ?? InputManager,
+ layoutManager: layoutManager ?? LayoutManager,
+ platformWrapper: platformWrapper ?? PlatformWrapper,
+ renderInterface: renderInterface ?? RenderInterface,
+ standardCursorFactory: standardCursorFactory ?? StandardCursorFactory,
+ styler: styler ?? Styler,
+ theme: theme ?? Theme,
+ threadingInterface: threadingInterface ?? ThreadingInterface,
+ windowImpl: windowImpl ?? WindowImpl,
+ windowingPlatform: windowingPlatform ?? WindowingPlatform);
+ }
+ }
+}
diff --git a/tests/Perspex.UnitTests/TestTemplatedRoot.cs b/tests/Perspex.UnitTests/TestTemplatedRoot.cs
new file mode 100644
index 0000000000..c28b4c02a4
--- /dev/null
+++ b/tests/Perspex.UnitTests/TestTemplatedRoot.cs
@@ -0,0 +1,65 @@
+// 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.Controls.Presenters;
+using Perspex.Controls.Templates;
+using Perspex.Layout;
+using Perspex.Platform;
+using Perspex.Rendering;
+using Perspex.Styling;
+
+namespace Perspex.UnitTests
+{
+ public class TestTemplatedRoot : ContentControl, ILayoutRoot, INameScope, IRenderRoot, IStyleRoot
+ {
+ private readonly NameScope _nameScope = new NameScope();
+
+ public TestTemplatedRoot()
+ {
+ Template = new FuncControlTemplate(x => new ContentPresenter());
+ }
+
+ public event EventHandler Registered
+ {
+ add { _nameScope.Registered += value; }
+ remove { _nameScope.Registered -= value; }
+ }
+
+ public event EventHandler Unregistered
+ {
+ add { _nameScope.Unregistered += value; }
+ remove { _nameScope.Unregistered -= value; }
+ }
+
+ public Size ClientSize => new Size(100, 100);
+
+ public Size MaxClientSize => Size.Infinity;
+
+ public ILayoutManager LayoutManager => PerspexLocator.Current.GetService();
+
+ public IRenderTarget RenderTarget => null;
+
+ public IRenderQueueManager RenderQueueManager => null;
+
+ public Point PointToClient(Point p) => p;
+
+ public Point PointToScreen(Point p) => p;
+
+ void INameScope.Register(string name, object element)
+ {
+ _nameScope.Register(name, element);
+ }
+
+ object INameScope.Find(string name)
+ {
+ return _nameScope.Find(name);
+ }
+
+ void INameScope.Unregister(string name)
+ {
+ _nameScope.Unregister(name);
+ }
+ }
+}
diff --git a/tests/Perspex.UnitTests/UnitTestApplication.cs b/tests/Perspex.UnitTests/UnitTestApplication.cs
new file mode 100644
index 0000000000..4811ce4ee2
--- /dev/null
+++ b/tests/Perspex.UnitTests/UnitTestApplication.cs
@@ -0,0 +1,47 @@
+// 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.Input;
+using Perspex.Layout;
+using Perspex.Platform;
+using Perspex.Styling;
+
+namespace Perspex.UnitTests
+{
+ public class UnitTestApplication : Application
+ {
+ public UnitTestApplication(TestServices services)
+ {
+ Services = services ?? new TestServices();
+ RegisterServices();
+ Styles = Services.Theme?.Invoke();
+ }
+
+ public static new UnitTestApplication Current => (UnitTestApplication)Application.Current;
+
+ public TestServices Services { get; }
+
+ public static IDisposable Start(TestServices services = null)
+ {
+ var scope = PerspexLocator.EnterScope();
+ var app = new UnitTestApplication(services);
+ return scope;
+ }
+
+ protected override void RegisterServices()
+ {
+ PerspexLocator.CurrentMutable
+ .Bind().ToConstant(Services.AssetLoader)
+ .BindToSelf(this)
+ .Bind().ToConstant(Services.InputManager)
+ .Bind().ToConstant(Services.LayoutManager)
+ .Bind().ToConstant(Services.PlatformWrapper)
+ .Bind().ToConstant(Services.RenderInterface)
+ .Bind().ToConstant(Services.ThreadingInterface)
+ .Bind().ToConstant(Services.StandardCursorFactory)
+ .Bind().ToConstant(Services.Styler)
+ .Bind().ToConstant(Services.WindowingPlatform);
+ }
+ }
+}
diff --git a/tests/Perspex.UnitTests/app.config b/tests/Perspex.UnitTests/app.config
new file mode 100644
index 0000000000..fa66e8c206
--- /dev/null
+++ b/tests/Perspex.UnitTests/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Perspex.UnitTests/packages.config b/tests/Perspex.UnitTests/packages.config
new file mode 100644
index 0000000000..fcf0eab9f9
--- /dev/null
+++ b/tests/Perspex.UnitTests/packages.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file