From 9e369e96bec2dd1b961c2f176658fd5a1ea10696 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Wed, 19 Oct 2016 10:13:53 +0100 Subject: [PATCH 01/12] fix text height --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index e24b6053b0..c203bf10bf 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -590,7 +590,7 @@ namespace Avalonia.Skia else { var lastLine = _skiaLines[_skiaLines.Count - 1]; - _size = new Size(maxX, lastLine.Top + lastLine.Height + lastLineDescent); + _size = new Size(lastLine.Width, lastLine.Height); } } From a46b9a97669188ab84ec7f0503f482ddfbb4f3c7 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Wed, 19 Oct 2016 10:14:27 +0100 Subject: [PATCH 02/12] fix text vertical offset. --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index c203bf10bf..3d402df01f 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -522,7 +522,7 @@ namespace Avalonia.Skia _lineHeight = mDescent - mAscent; // Rendering is relative to baseline - _lineOffset = -metrics.Top; + _lineOffset = (-metrics.Ascent); string subString; From 6bde43372431ee06b68407b36c7d65291a2a7e42 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Thu, 20 Oct 2016 16:49:54 +0100 Subject: [PATCH 03/12] correctly setting size to cope with text wrapping. --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 3d402df01f..51f4b2b724 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -590,7 +590,7 @@ namespace Avalonia.Skia else { var lastLine = _skiaLines[_skiaLines.Count - 1]; - _size = new Size(lastLine.Width, lastLine.Height); + _size = new Size(maxX, lastLine.Top + lastLine.Height); } } From 01a1608a8d3d078e69d5e9473390c7cbd93581d5 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 28 Oct 2016 22:51:14 +0200 Subject: [PATCH 04/12] Call SetFocus in ShowWindow. Dialogs weren't receiving text input (WM_CHAR) after being shown (though they were receiving key down/up messages). Fixes #785. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 65e10cafda..5db3f69f85 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -682,6 +682,7 @@ namespace Avalonia.Win32 } UnmanagedMethods.ShowWindow(_hwnd, command); + UnmanagedMethods.SetFocus(_hwnd); } public void SetIcon(IWindowIconImpl icon) From b28fffc3f8aae18a90b0dd21676e36da72831172 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 30 Oct 2016 20:51:47 +0100 Subject: [PATCH 05/12] Coerce TextBox.CaretIndex when setting Text. Fixes #728 . --- src/Avalonia.Controls/TextBox.cs | 6 ++-- .../TextBoxTests.cs | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 7a271e8615..719e888dd4 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -202,6 +202,7 @@ namespace Avalonia.Controls { if (!_ignoreTextChanges) { + CaretIndex = CoerceCaretIndex(CaretIndex, value?.Length ?? 0); SetAndRaise(TextProperty, ref _text, value); } } @@ -558,10 +559,11 @@ namespace Avalonia.Controls return null; } - private int CoerceCaretIndex(int value) + private int CoerceCaretIndex(int value) => CoerceCaretIndex(value, Text?.Length ?? 0); + + private int CoerceCaretIndex(int value, int length) { var text = Text; - var length = text?.Length ?? 0; if (value < 0) { diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index cff49bc32e..26fc2a2461 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -1,6 +1,8 @@ // Copyright (c) The Avalonia 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.Reactive.Linq; using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; @@ -200,6 +202,33 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Setting_Text_Updates_CaretPosition() + { + using (UnitTestApplication.Start(Services)) + { + var target = new TextBox + { + Text = "Initial Text", + CaretIndex = 11 + }; + + var invoked = false; + + target.GetObservable(TextBox.TextProperty).Skip(1).Subscribe(_ => + { + // Caret index should be set before Text changed notification, as we don't want + // to notify with an invalid CaretIndex. + Assert.Equal(7, target.CaretIndex); + invoked = true; + }); + + target.Text = "Changed"; + + Assert.True(invoked); + } + } + private static TestServices Services => TestServices.MockThreadingInterface.With( standardCursorFactory: Mock.Of()); From c86e750281480fd960d3b5a47d9df11a4969d3b0 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 19 Sep 2016 17:01:13 -0500 Subject: [PATCH 06/12] Add OpenCover coverage testing for Windows builds. --- build.cake | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/build.cake b/build.cake index d97d17218c..6192e0f88d 100644 --- a/build.cake +++ b/build.cake @@ -10,6 +10,7 @@ /////////////////////////////////////////////////////////////////////////////// #tool "nuget:?package=xunit.runner.console&version=2.1.0" +#tool "nuget:?package=OpenCover" /////////////////////////////////////////////////////////////////////////////// // USINGS @@ -670,18 +671,35 @@ Task("Run-Unit-Tests") "./tools/xunit.runner.console/tools/xunit.console.x86.exe" : "./tools/xunit.runner.console/tools/xunit.console.exe"; - var settings = new XUnit2Settings + var xUnitSettings = new XUnit2Settings { ToolPath = toolPath, - Parallelism = ParallelismOption.None + Parallelism = ParallelismOption.None, + ShadowCopy = false }; - settings.NoAppDomain = !isRunningOnWindows; + xUnitSettings.NoAppDomain = !isRunningOnWindows; + + var openCoverOutput = artifactsDir.GetFilePath(new FilePath("./result.xml")); + var openCoverSettings = new OpenCoverSettings + { + ArgumentCustomization = openCoverArgs => openCoverArgs.AppendSwitch("-mergeoutput", "") + } + .WithFilter("+[Avalonia.*]* -[*Test*]*");; foreach (var file in unitTests) { Information("Running test " + file.GetFilenameWithoutExtension()); - XUnit2(file.FullPath, settings); + if(isRunningOnWindows) + { + OpenCover(context => { + context.XUnit2(file.FullPath, xUnitSettings); + }, openCoverOutput, openCoverSettings); + } + else + { + XUnit2(file.FullPath, xUnitSettings); + } } }); From 5edb20fdfed4db6f1fff2b5708cb505c60a74d14 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 21 Sep 2016 11:48:48 -0500 Subject: [PATCH 07/12] Added CodeCov uploading. --- appveyor.yml | 5 +++++ build.cake | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2909da65b7..db7d129dd1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,6 +20,11 @@ build_script: - ps: .\build.ps1 -Target "AppVeyor" -Platform "$env:platform" -Configuration "$env:configuration" after_build: - .\packages\JetBrains.dotMemoryUnit.2.1.20150828.125449\tools\dotMemoryUnit.exe -targetExecutable="%xunit20%\xunit.console.x86.exe" -returnTargetExitCode --"tests\Avalonia.LeakTests\bin\Release\Avalonia.LeakTests.dll" + +- "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%" +- pip install codecov +- codecov -f "./artifacts/coverage.xml" + test: off artifacts: - path: artifacts\nuget\*.nupkg diff --git a/build.cake b/build.cake index 6192e0f88d..2e63e83d61 100644 --- a/build.cake +++ b/build.cake @@ -680,7 +680,7 @@ Task("Run-Unit-Tests") xUnitSettings.NoAppDomain = !isRunningOnWindows; - var openCoverOutput = artifactsDir.GetFilePath(new FilePath("./result.xml")); + var openCoverOutput = artifactsDir.GetFilePath(new FilePath("./coverage.xml")); var openCoverSettings = new OpenCoverSettings { ArgumentCustomization = openCoverArgs => openCoverArgs.AppendSwitch("-mergeoutput", "") From b6e062ed8aaff7e6b06db99a71d6bacaaa240819 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 22 Sep 2016 23:14:23 -0500 Subject: [PATCH 08/12] Add initial Coveralls.io publishing --- build.cake | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/build.cake b/build.cake index 2e63e83d61..0315a36df2 100644 --- a/build.cake +++ b/build.cake @@ -4,6 +4,7 @@ #addin "nuget:?package=Polly&version=4.2.0" #addin "nuget:?package=NuGet.Core&version=2.12.0" +#addin Cake.Coveralls /////////////////////////////////////////////////////////////////////////////// // TOOLS @@ -11,6 +12,7 @@ #tool "nuget:?package=xunit.runner.console&version=2.1.0" #tool "nuget:?package=OpenCover" +#tool coveralls.net /////////////////////////////////////////////////////////////////////////////// // USINGS @@ -800,6 +802,14 @@ Task("Publish-NuGet") Information("Publish-NuGet Task failed, but continuing with next Task..."); }); +Task("Publish-Coverage") + .IsDependentOn("Run-Unit-Tests") + .WithCriteria(() => isRunningOnAppVeyor) + .Does(() => +{ + CoverallsNet(artifactsDir.GetFilePath(new FilePath("./coverage.xml")), CoverallsNetReportType.OpenCover); +}); + /////////////////////////////////////////////////////////////////////////////// // TARGETS /////////////////////////////////////////////////////////////////////////////// @@ -813,7 +823,8 @@ Task("Default") Task("AppVeyor") .IsDependentOn("Zip-Files") .IsDependentOn("Publish-MyGet") - .IsDependentOn("Publish-NuGet"); + .IsDependentOn("Publish-NuGet") + .IsDependentOn("Publish-Coverage"); Task("Travis") .IsDependentOn("Run-Unit-Tests"); From 57750c8cfe726587cc04b4225e074885f8b8accb Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 22 Sep 2016 23:26:50 -0500 Subject: [PATCH 09/12] Added Coveralls credentials and settings --- build.cake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.cake b/build.cake index 0315a36df2..d735489d5c 100644 --- a/build.cake +++ b/build.cake @@ -807,7 +807,8 @@ Task("Publish-Coverage") .WithCriteria(() => isRunningOnAppVeyor) .Does(() => { - CoverallsNet(artifactsDir.GetFilePath(new FilePath("./coverage.xml")), CoverallsNetReportType.OpenCover); + CoverallsNet(artifactsDir.GetFilePath(new FilePath("./coverage.xml")), CoverallsNetReportType.OpenCover, + new CoverallsNetSettings {RepoToken = "jKaVvndtCVJ2y7pNwQtYeHPn2jAxUpuyh", UseRelativePaths = true, ServiceName = "AppVeyor"}); }); /////////////////////////////////////////////////////////////////////////////// From 22b89ed8971924d9e24a1383fc39fbba1ce341c0 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sun, 2 Oct 2016 16:14:51 -0500 Subject: [PATCH 10/12] Copy all tests to a test directory under artifacts to prevent collecting coverage for multiple copies of the same assembly in multiple different areas. (Massively shrinks the coverage.xml file). --- build.cake | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/build.cake b/build.cake index d735489d5c..269b17271e 100644 --- a/build.cake +++ b/build.cake @@ -95,6 +95,7 @@ var artifactsDir = (DirectoryPath)Directory("./artifacts"); var nugetRoot = artifactsDir.Combine("nuget"); var zipRoot = artifactsDir.Combine("zip"); var binRoot = artifactsDir.Combine("bin"); +var testsRoot = artifactsDir.Combine("tests"); var dirSuffix = configuration; var dirSuffixSkia = (isPlatformAnyCPU ? "x86" : platform) + "/" + configuration; @@ -588,6 +589,7 @@ Task("Clean") CleanDirectory(nugetRoot); CleanDirectory(zipRoot); CleanDirectory(binRoot); + CleanDirectory(testsRoot); }); Task("Restore-NuGet-Packages") @@ -683,25 +685,25 @@ Task("Run-Unit-Tests") xUnitSettings.NoAppDomain = !isRunningOnWindows; var openCoverOutput = artifactsDir.GetFilePath(new FilePath("./coverage.xml")); - var openCoverSettings = new OpenCoverSettings - { - ArgumentCustomization = openCoverArgs => openCoverArgs.AppendSwitch("-mergeoutput", "") - } - .WithFilter("+[Avalonia.*]* -[*Test*]*");; + var openCoverSettings = new OpenCoverSettings() + .WithFilter("+[Avalonia.*]* -[*Test*]* -[ControlCatalog*]*") + .WithFilter("-[Avalonia.*]OmniXaml.* -[Avalonia.*]Glass.*") + .WithFilter("-[Avalonia.HtmlRenderer]TheArtOfDev.HtmlRenderer.* +[Avalonia.HtmlRenderer]TheArtOfDev.HtmlRenderer.Avalonia.* -[Avalonia.ReactiveUI]*"); + + foreach(var test in unitTests) + { + CopyDirectory(test.GetDirectory(), testsRoot); + } - foreach (var file in unitTests) + if(isRunningOnWindows) { - Information("Running test " + file.GetFilenameWithoutExtension()); - if(isRunningOnWindows) - { - OpenCover(context => { - context.XUnit2(file.FullPath, xUnitSettings); - }, openCoverOutput, openCoverSettings); - } - else - { - XUnit2(file.FullPath, xUnitSettings); - } + OpenCover(context => { + context.XUnit2(unitTests.Select(test => testsRoot.GetFilePath(test).FullPath), xUnitSettings); + }, openCoverOutput, openCoverSettings); + } + else + { + XUnit2(unitTests.Select(test => test.FullPath), xUnitSettings); } }); From 33df423ef531501ca6b92562e59cc92ab8a09f10 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 2 Nov 2016 15:16:00 -0500 Subject: [PATCH 11/12] Remove Coveralls.io coverage support since we are using CodeCov instead. --- build.cake | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/build.cake b/build.cake index 269b17271e..82fa0b83f3 100644 --- a/build.cake +++ b/build.cake @@ -4,7 +4,6 @@ #addin "nuget:?package=Polly&version=4.2.0" #addin "nuget:?package=NuGet.Core&version=2.12.0" -#addin Cake.Coveralls /////////////////////////////////////////////////////////////////////////////// // TOOLS @@ -12,7 +11,6 @@ #tool "nuget:?package=xunit.runner.console&version=2.1.0" #tool "nuget:?package=OpenCover" -#tool coveralls.net /////////////////////////////////////////////////////////////////////////////// // USINGS @@ -804,15 +802,6 @@ Task("Publish-NuGet") Information("Publish-NuGet Task failed, but continuing with next Task..."); }); -Task("Publish-Coverage") - .IsDependentOn("Run-Unit-Tests") - .WithCriteria(() => isRunningOnAppVeyor) - .Does(() => -{ - CoverallsNet(artifactsDir.GetFilePath(new FilePath("./coverage.xml")), CoverallsNetReportType.OpenCover, - new CoverallsNetSettings {RepoToken = "jKaVvndtCVJ2y7pNwQtYeHPn2jAxUpuyh", UseRelativePaths = true, ServiceName = "AppVeyor"}); -}); - /////////////////////////////////////////////////////////////////////////////// // TARGETS /////////////////////////////////////////////////////////////////////////////// @@ -826,8 +815,7 @@ Task("Default") Task("AppVeyor") .IsDependentOn("Zip-Files") .IsDependentOn("Publish-MyGet") - .IsDependentOn("Publish-NuGet") - .IsDependentOn("Publish-Coverage"); + .IsDependentOn("Publish-NuGet"); Task("Travis") .IsDependentOn("Run-Unit-Tests"); From 26e60f9935511fbd46db63a92e746d504d59248d Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 2 Nov 2016 15:35:39 -0500 Subject: [PATCH 12/12] Moved failing test into LeakTests because it depends on runtime implementation details to pass. --- .../Avalonia.LeakTests.csproj | 1 + .../Avalonia.LeakTests/MemberSelectorTests.cs | 47 +++++++++++++++++++ .../Templates/MemberSelectorTests.cs | 26 ---------- 3 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 tests/Avalonia.LeakTests/MemberSelectorTests.cs diff --git a/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj b/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj index 9aef304beb..7fed908927 100644 --- a/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj +++ b/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj @@ -99,6 +99,7 @@ + diff --git a/tests/Avalonia.LeakTests/MemberSelectorTests.cs b/tests/Avalonia.LeakTests/MemberSelectorTests.cs new file mode 100644 index 0000000000..d794e788fd --- /dev/null +++ b/tests/Avalonia.LeakTests/MemberSelectorTests.cs @@ -0,0 +1,47 @@ +using Avalonia.Markup.Xaml.Templates; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Avalonia.LeakTests +{ + public class MemberSelectorTests + { + [Fact] + public void Should_Not_Hold_Reference_To_Object() + { + WeakReference dataRef = null; + + var selector = new MemberSelector() { MemberName = "Child.StringValue" }; + + Action run = () => + { + var data = new Item() + { + Child = new Item() { StringValue = "Value1" } + }; + + Assert.Same("Value1", selector.Select(data)); + + dataRef = new WeakReference(data); + }; + + run(); + + GC.Collect(); + + Assert.False(dataRef.IsAlive); + } + + private class Item + { + public Item Child { get; set; } + public int IntValue { get; set; } + + public string StringValue { get; set; } + } + } +} diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs index 7082863c0d..49a88e8fae 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs @@ -9,32 +9,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Templates { public class MemberSelectorTests { - [Fact] - public void Should_Not_Hold_Reference_To_Object() - { - WeakReference dataRef = null; - - var selector = new MemberSelector() { MemberName = "Child.StringValue" }; - - Action run = () => - { - var data = new Item() - { - Child = new Item() { StringValue = "Value1" } - }; - - Assert.Same("Value1", selector.Select(data)); - - dataRef = new WeakReference(data); - }; - - run(); - - GC.Collect(); - - Assert.False(dataRef.IsAlive); - } - [Fact] public void Should_Select_Child_Property_Value() {