diff --git a/nukebuild/BuildParameters.cs b/nukebuild/BuildParameters.cs index 5f8ec7267e..afd1950859 100644 --- a/nukebuild/BuildParameters.cs +++ b/nukebuild/BuildParameters.cs @@ -14,13 +14,13 @@ using static Nuke.Common.Tools.MSBuild.MSBuildTasks; public partial class Build { [Parameter("configuration")] - public string NukeArgConfiguration { get; set; } + public string Configuration { get; set; } [Parameter("skip-tests")] - public bool NukeArgSkipTests { get; set; } + public bool SkipTests { get; set; } [Parameter("force-nuget-version")] - public string NukeArgForceNugetVersion { get; set; } + public string ForceNugetVersion { get; set; } public class BuildParameters { @@ -64,8 +64,8 @@ public partial class Build public BuildParameters(Build b) { // ARGUMENTS - Configuration = b.NukeArgConfiguration ?? "Release"; - SkipTests = b.NukeArgSkipTests; + Configuration = b.Configuration ?? "Release"; + SkipTests = b.SkipTests; // CONFIGURATION MainRepo = "https://github.com/AvaloniaUI/Avalonia"; @@ -102,7 +102,7 @@ public partial class Build IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; // VERSION - Version = b.NukeArgForceNugetVersion ?? GetVersion(); + Version = b.ForceNugetVersion ?? GetVersion(); if (IsRunningOnAzure) { diff --git a/parameters.cake b/parameters.cake deleted file mode 100644 index 4ef7e8e05a..0000000000 --- a/parameters.cake +++ /dev/null @@ -1,129 +0,0 @@ -using System.Xml.Linq; -using System.Linq; - -public class Parameters -{ - public string Configuration { get; private set; } - public bool SkipTests { get; private set; } - public string MainRepo { get; private set; } - public string MasterBranch { get; private set; } - public string ReleasePlatform { get; private set; } - public string ReleaseConfiguration { get; private set; } - public string ReleaseBranchPrefix { get; private set; } - public string MSBuildSolution { get; private set; } - public bool IsLocalBuild { get; private set; } - public bool IsRunningOnUnix { get; private set; } - public bool IsRunningOnWindows { get; private set; } - public bool IsRunningOnAppVeyor { get; private set; } - public bool IsRunningOnAzure { get; private set; } - public bool IsPullRequest { get; private set; } - public bool IsMainRepo { get; private set; } - public bool IsMasterBranch { get; private set; } - public bool IsReleaseBranch { get; private set; } - public bool IsTagged { get; private set; } - public bool IsReleasable { get; private set; } - public bool IsMyGetRelease { get; private set; } - public bool IsNuGetRelease { get; private set; } - public bool PublishTestResults { get; private set; } - public string Version { get; private set; } - public DirectoryPath ArtifactsDir { get; private set; } - public DirectoryPath NugetRoot { get; private set; } - public DirectoryPath ZipRoot { get; private set; } - public DirectoryPath BinRoot { get; private set; } - public DirectoryPath TestResultsRoot { get; private set; } - public string DirSuffix { get; private set; } - public DirectoryPathCollection BuildDirs { get; private set; } - public string FileZipSuffix { get; private set; } - public FilePath ZipCoreArtifacts { get; private set; } - public FilePath ZipNuGetArtifacts { get; private set; } - public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; } - public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; } - - public Parameters(ICakeContext context) - { - var buildSystem = context.BuildSystem(); - - // ARGUMENTS - Configuration = context.Argument("configuration", "Release"); - SkipTests = context.HasArgument("skip-tests"); - - // CONFIGURATION - MainRepo = "https://github.com/AvaloniaUI/Avalonia"; - MasterBranch = "master"; - ReleaseBranchPrefix = "refs/heads/release/"; - ReleaseConfiguration = "Release"; - MSBuildSolution = "./dirs.proj"; - - // PARAMETERS - IsLocalBuild = buildSystem.IsLocalBuild; - IsRunningOnUnix = context.IsRunningOnUnix(); - IsRunningOnWindows = context.IsRunningOnWindows(); - IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor; - IsRunningOnAzure = buildSystem.IsRunningOnVSTS || buildSystem.IsRunningOnTFS || context.EnvironmentVariable("LOGNAME") == "vsts"; - - IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; - IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI")); - IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); - IsReleaseBranch = (context.EnvironmentVariable("BUILD_SOURCEBRANCH")??"").StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase); - IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag - && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name); - IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); - IsMyGetRelease = !IsTagged && IsReleasable; - IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; - - // VERSION - Version = context.Argument("force-nuget-version", GetVersion()); - - if (IsRunningOnAppVeyor) - { - string tagVersion = null; - if (IsTagged) - { - var tag = buildSystem.AppVeyor.Environment.Repository.Tag.Name; - var nugetReleasePrefix = "nuget-release-"; - IsNuGetRelease = IsTagged && IsReleasable && tag.StartsWith(nugetReleasePrefix); - if(IsNuGetRelease) - tagVersion = tag.Substring(nugetReleasePrefix.Length); - } - if(tagVersion != null) - { - Version = tagVersion; - } - else - { - // Use AssemblyVersion with Build as version - Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta"; - } - } - else if (IsRunningOnAzure) - { - if(!IsNuGetRelease) - { - // Use AssemblyVersion with Build as version - Version += "-build" + context.EnvironmentVariable("BUILD_BUILDID") + "-beta"; - } - - PublishTestResults = true; - } - - // DIRECTORIES - ArtifactsDir = (DirectoryPath)context.Directory("./artifacts"); - NugetRoot = ArtifactsDir.Combine("nuget"); - ZipRoot = ArtifactsDir.Combine("zip"); - BinRoot = ArtifactsDir.Combine("bin"); - TestResultsRoot = ArtifactsDir.Combine("test-results"); - BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj"); - DirSuffix = Configuration; - FileZipSuffix = Version + ".zip"; - ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix); - ZipNuGetArtifacts = ZipRoot.CombineWithFilePath("Avalonia-NuGet-" + FileZipSuffix); - ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461"); - ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix); - } - - private static string GetVersion() - { - var xdoc = XDocument.Load("./build/SharedVersion.props"); - return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value; - } -} diff --git a/src/Avalonia.Base/Data/Core/ExpressionNode.cs b/src/Avalonia.Base/Data/Core/ExpressionNode.cs index f2f3ed9bfc..8a2dd46b86 100644 --- a/src/Avalonia.Base/Data/Core/ExpressionNode.cs +++ b/src/Avalonia.Base/Data/Core/ExpressionNode.cs @@ -147,6 +147,7 @@ namespace Avalonia.Data.Core private void StopListening() { StopListeningCore(); + _listening = false; } private BindingNotification TargetNullNotification() diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs index b177dc50cf..f72a65ead2 100644 --- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs +++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs @@ -517,7 +517,7 @@ namespace Avalonia.Controls.Presenters if (index >= 0 && index < ItemCount) { - if (index < FirstIndex) + if (index <= FirstIndex) { newOffset = index; } @@ -525,10 +525,6 @@ namespace Avalonia.Controls.Presenters { newOffset = index - Math.Ceiling(ViewportValue - 1); } - else if (OffsetValue + ViewportValue >= ItemCount) - { - newOffset = OffsetValue - 1; - } if (newOffset != -1) { @@ -546,6 +542,11 @@ namespace Avalonia.Controls.Presenters { layoutManager.ExecuteLayoutPass(); + if (newOffset != -1 && newOffset != OffsetValue) + { + OffsetValue = newOffset; + } + if (panel.ScrollDirection == Orientation.Vertical) { if (container.Bounds.Y < panel.Bounds.Y || container.Bounds.Bottom > panel.Bounds.Bottom) diff --git a/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs b/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs index 25f12ffa57..541e8646b1 100644 --- a/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs +++ b/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs @@ -72,11 +72,7 @@ namespace Avalonia.Styling /// protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) { - if (!AvaloniaPropertyRegistry.Instance.IsRegistered(control, _property)) - { - return SelectorMatch.False; - } - else if (subscribe) + if (subscribe) { return new SelectorMatch(control.GetObservable(_property).Select(v => Equals(v ?? string.Empty, _value))); } diff --git a/src/Avalonia.Visuals/Matrix.cs b/src/Avalonia.Visuals/Matrix.cs index cdaaa2b4b4..d083a2aaf8 100644 --- a/src/Avalonia.Visuals/Matrix.cs +++ b/src/Avalonia.Visuals/Matrix.cs @@ -293,13 +293,13 @@ namespace Avalonia /// The inverted matrix. public Matrix Invert() { - if (GetDeterminant() == 0) + double d = GetDeterminant(); + + if (d == 0) { throw new InvalidOperationException("Transform is not invertible."); } - double d = GetDeterminant(); - return new Matrix( _m22 / d, -_m12 / d, diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 6174bc360f..f4eb0e2ea8 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -153,17 +153,24 @@ namespace Avalonia.Win32 public void Resize(Size value) { - if (value != ClientSize) + int requestedClientWidth = (int)(value.Width * Scaling); + int requestedClientHeight = (int)(value.Height * Scaling); + UnmanagedMethods.RECT clientRect; + UnmanagedMethods.GetClientRect(_hwnd, out clientRect); + + // do comparison after scaling to avoid rounding issues + if (requestedClientWidth != clientRect.Width || requestedClientHeight != clientRect.Height) { - value *= Scaling; - + UnmanagedMethods.RECT windowRect; + UnmanagedMethods.GetWindowRect(_hwnd, out windowRect); + UnmanagedMethods.SetWindowPos( _hwnd, IntPtr.Zero, 0, 0, - (int)value.Width, - (int)value.Height, + requestedClientWidth + (windowRect.Width - clientRect.Width), + requestedClientHeight + (windowRect.Height - clientRect.Height), UnmanagedMethods.SetWindowPosFlags.SWP_RESIZE); } } diff --git a/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs index c90683959e..f282d1baf3 100644 --- a/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs +++ b/tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs @@ -563,6 +563,19 @@ namespace Avalonia.Base.UnitTests.Data.Core Assert.Null(result.Item2.Target); } + [Fact] + public void Should_Not_Throw_Exception_On_Unsubscribe_When_Already_Unsubscribed() + { + var source = new Class1 { Foo = "foo" }; + var target = new PropertyAccessorNode("Foo", false); + Assert.NotNull(target); + target.Target = new WeakReference(source); + target.Subscribe(_ => { }); + target.Unsubscribe(); + target.Unsubscribe(); + Assert.True(true); + } + private interface INext { int PropertyChangedSubscriptionCount { get; } diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs index b992453fb0..7187ea16da 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs @@ -717,6 +717,45 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(10, target.Panel.Children.Count); } + [Fact] + public void Scroll_To_Last_Should_Work() + { + var target = CreateTarget(itemCount: 11); + var scroller = (TestScroller)target.Parent; + + scroller.Width = scroller.Height = 100; + scroller.LayoutManager.ExecuteInitialLayoutPass(scroller); + + var last = (target.Items as IList)[10]; + + target.ScrollIntoView(last); + + Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset); + Assert.Same(target.Panel.Children[9].DataContext, last); + } + + [Fact] + public void Second_Scroll_To_Last_Should_Work() + { + var target = CreateTarget(itemCount: 11); + var scroller = (TestScroller)target.Parent; + + scroller.Width = scroller.Height = 100; + scroller.LayoutManager.ExecuteInitialLayoutPass(scroller); + + var last = (target.Items as IList)[10]; + + target.ScrollIntoView(last); + + Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset); + Assert.Same(target.Panel.Children[9].DataContext, last); + + target.ScrollIntoView(last); + + Assert.Equal(new Vector(0, 1), ((ILogicalScrollable)target).Offset); + Assert.Same(target.Panel.Children[9].DataContext, last); + } + public class Vertical { [Fact] @@ -1090,4 +1129,4 @@ namespace Avalonia.Controls.UnitTests.Presenters } } } -} \ No newline at end of file +} diff --git a/tools/packages.config b/tools/packages.config deleted file mode 100644 index 05018882e8..0000000000 --- a/tools/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - -