From b6447c0e0920966eeaf2052934651a360a7722c9 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 1 Oct 2019 19:06:00 +0300 Subject: [PATCH 1/7] failing test for #3053 --- .../Media/PathMarkupParserTests.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs index 5570378063..5cdbcd9116 100644 --- a/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs @@ -235,5 +235,30 @@ namespace Avalonia.Visuals.UnitTests.Media Assert.Throws(() => parser.Parse(pathData)); } } + + [Fact] + public void CloseFigure_Should_Move_CurrentPoint_To_CreateFigurePoint() + { + var pathGeometry = new PathGeometry(); + using (var context = new PathGeometryContext(pathGeometry)) + using (var parser = new PathMarkupParser(context)) + { + parser.Parse("M10,10L100,100Z m10,10"); + + Assert.Equal(2, pathGeometry.Figures.Count); + + var figure = pathGeometry.Figures[0]; + + Assert.Equal(new Point(10, 10), figure.StartPoint); + + Assert.Equal(true, figure.IsClosed); + + Assert.Equal(new Point(100, 100), ((LineSegment)figure.Segments[0]).Point); + + figure = pathGeometry.Figures[1]; + + Assert.Equal(new Point(20, 20), figure.StartPoint); + } + } } } From 2b9180c794b77e6ca5db4f5519929b6b5fcdfc8d Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 1 Oct 2019 22:27:10 +0300 Subject: [PATCH 2/7] fix invalid test related to issue #3053 --- .../Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs index 5cdbcd9116..e1475dce80 100644 --- a/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs @@ -100,9 +100,7 @@ namespace Avalonia.Visuals.UnitTests.Media Assert.Equal(new Point(10, 10), lineSegment.Point); - figure = pathGeometry.Figures[1]; - - segment = figure.Segments[0]; + segment = figure.Segments[1]; Assert.IsType(segment); From a675cd2e687f53a79404769c149e1e37e36f4ac4 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 1 Oct 2019 22:43:14 +0300 Subject: [PATCH 3/7] when close figure set current point back to start, fixes partially #3053 --- src/Avalonia.Visuals/Media/PathMarkupParser.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Avalonia.Visuals/Media/PathMarkupParser.cs b/src/Avalonia.Visuals/Media/PathMarkupParser.cs index 8852883dcc..c93edaca14 100644 --- a/src/Avalonia.Visuals/Media/PathMarkupParser.cs +++ b/src/Avalonia.Visuals/Media/PathMarkupParser.cs @@ -32,6 +32,7 @@ namespace Avalonia.Media private IGeometryContext _geometryContext; private Point _currentPoint; + private Point? _beginFigurePoint; private Point? _previousControlPoint; private bool _isOpen; private bool _isDisposed; @@ -180,6 +181,8 @@ namespace Avalonia.Media _geometryContext.BeginFigure(_currentPoint); + _beginFigurePoint = _currentPoint; + _isOpen = true; } @@ -212,6 +215,12 @@ namespace Avalonia.Media if (_isOpen) { _geometryContext.EndFigure(true); + + if (_beginFigurePoint != null) + { + _currentPoint = _beginFigurePoint.Value; + _beginFigurePoint = null; + } } _previousControlPoint = null; From f4c7f63ae7ca14c92248e7f71a752d632b75cde3 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 1 Oct 2019 22:45:24 +0300 Subject: [PATCH 4/7] remove wrong logic for path assume line by default if command is missing --- src/Avalonia.Visuals/Media/PathMarkupParser.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Avalonia.Visuals/Media/PathMarkupParser.cs b/src/Avalonia.Visuals/Media/PathMarkupParser.cs index c93edaca14..e8f149df11 100644 --- a/src/Avalonia.Visuals/Media/PathMarkupParser.cs +++ b/src/Avalonia.Visuals/Media/PathMarkupParser.cs @@ -242,12 +242,6 @@ namespace Avalonia.Media { span = ReadSeparator(span); AddLine(ref span, relative); - - if (!relative) - { - _currentPoint = currentPoint; - CreateFigure(); - } } } From 8093716a3680cc6a7e53195cca14269d7fb25b28 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 2 Oct 2019 13:04:04 +0200 Subject: [PATCH 5/7] Added tests for selection after initialization. --- .../Primitives/SelectingItemsControlTests.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs index 8f27ebe853..d5237e2aca 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs @@ -109,6 +109,43 @@ namespace Avalonia.Controls.UnitTests.Primitives Assert.True(items[1].IsSelected); } + [Fact] + public void SelectedIndex_Should_Be_Minus_1_After_Initialize() + { + var items = new[] + { + new Item(), + new Item(), + }; + + var target = new ListBox(); + target.BeginInit(); + target.Items = items; + target.Template = Template(); + target.EndInit(); + + Assert.Equal(-1, target.SelectedIndex); + } + + [Fact] + public void SelectedIndex_Should_Be_0_After_Initialize_With_AlwaysSelected() + { + var items = new[] + { + new Item(), + new Item(), + }; + + var target = new ListBox(); + target.BeginInit(); + target.SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected; + target.Items = items; + target.Template = Template(); + target.EndInit(); + + Assert.Equal(0, target.SelectedIndex); + } + [Fact] public void Setting_SelectedIndex_During_Initialize_Should_Select_Item_When_AlwaysSelected_Is_Used() { From 60e3c3c9772d413f9ac02d6d1869bfb4a9827eed Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 2 Oct 2019 13:06:15 +0200 Subject: [PATCH 6/7] Fix selection after initialization. Fixes first item in menus being selected when menu is shown. --- src/Avalonia.Controls/Primitives/SelectingItemsControl.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index a50175bdee..6869ea0822 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -1088,7 +1088,9 @@ namespace Avalonia.Controls.Primitives } else { - SelectedIndex = _updateSelectedIndex != int.MinValue ? _updateSelectedIndex : 0; + SelectedIndex = _updateSelectedIndex != int.MinValue ? + _updateSelectedIndex : + AlwaysSelected ? 0 : -1; } } } From 15e15f227f0f11bc38b7b42f42ca818676d55613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Wed, 2 Oct 2019 14:17:04 +0200 Subject: [PATCH 7/7] Fix double dispose of bindings caused by animations. Add assertion for double dispose. --- .../DisposeAnimationInstanceSubject.cs | 16 ++++++++-------- src/Avalonia.Base/PriorityLevel.cs | 19 +++++++++++++++---- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Animation/DisposeAnimationInstanceSubject.cs b/src/Avalonia.Animation/DisposeAnimationInstanceSubject.cs index b44f392ce3..0c15524362 100644 --- a/src/Avalonia.Animation/DisposeAnimationInstanceSubject.cs +++ b/src/Avalonia.Animation/DisposeAnimationInstanceSubject.cs @@ -2,14 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Linq; using Avalonia.Animation.Animators; -using Avalonia.Animation.Utils; -using Avalonia.Collections; -using Avalonia.Data; -using Avalonia.Reactive; namespace Avalonia.Animation { @@ -46,6 +39,7 @@ namespace Avalonia.Animation public void OnError(Exception error) { _lastInstance?.Dispose(); + _lastInstance = null; } void IObserver.OnNext(bool matchVal) @@ -53,12 +47,18 @@ namespace Avalonia.Animation if (matchVal != _lastMatch) { _lastInstance?.Dispose(); + if (matchVal) { _lastInstance = _animator.Run(_animation, _control, _clock, _onComplete); } + else + { + _lastInstance = null; + } + _lastMatch = matchVal; } } } -} \ No newline at end of file +} diff --git a/src/Avalonia.Base/PriorityLevel.cs b/src/Avalonia.Base/PriorityLevel.cs index 6366911e77..a2364083ea 100644 --- a/src/Avalonia.Base/PriorityLevel.cs +++ b/src/Avalonia.Base/PriorityLevel.cs @@ -3,7 +3,8 @@ using System; using System.Collections.Generic; -using System.Reactive.Disposables; +using System.Diagnostics; +using System.Threading; using Avalonia.Data; namespace Avalonia @@ -181,9 +182,9 @@ namespace Avalonia private sealed class RemoveBindingDisposable : IDisposable { - private readonly LinkedListNode _binding; private readonly LinkedList _bindings; private readonly PriorityLevel _priorityLevel; + private LinkedListNode _binding; public RemoveBindingDisposable( LinkedListNode binding, @@ -197,11 +198,21 @@ namespace Avalonia public void Dispose() { - PriorityBindingEntry entry = _binding.Value; + LinkedListNode binding = Interlocked.Exchange(ref _binding, null); + + if (binding == null) + { + // Some system is trying to remove binding twice. + Debug.Assert(false); + + return; + } + + PriorityBindingEntry entry = binding.Value; if (!entry.HasCompleted) { - _bindings.Remove(_binding); + _bindings.Remove(binding); entry.Dispose();