From cad119ebfbf16d5d792e63d0991cb153000baad7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 16 Jul 2019 11:35:36 +0200 Subject: [PATCH] Invalidate Pen when properties change. --- src/Avalonia.Visuals/Media/Pen.cs | 61 +++++++++++++++++++ .../Media/PenTests.cs | 33 ++++++++++ 2 files changed, 94 insertions(+) create mode 100644 tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs diff --git a/src/Avalonia.Visuals/Media/Pen.cs b/src/Avalonia.Visuals/Media/Pen.cs index 2bfd4f472e..64c4e4ce44 100644 --- a/src/Avalonia.Visuals/Media/Pen.cs +++ b/src/Avalonia.Visuals/Media/Pen.cs @@ -3,6 +3,7 @@ using System; using Avalonia.Media.Immutable; +using Avalonia.Utilities; namespace Avalonia.Media { @@ -98,6 +99,17 @@ namespace Avalonia.Media DashStyle = dashStyle; } + static Pen() + { + AffectsRender( + BrushProperty, + ThicknessProperty, + DashStyleProperty, + LineCapProperty, + LineJoinProperty, + MiterLimitProperty); + } + /// /// Gets or sets the brush used to draw the stroke. /// @@ -172,5 +184,54 @@ namespace Avalonia.Media LineJoin, MiterLimit); } + + /// + /// Marks a property as affecting the pen's visual representation. + /// + /// The properties. + /// + /// After a call to this method in a pen's static constructor, any change to the + /// property will cause the event to be raised on the pen. + /// + protected static void AffectsRender(params AvaloniaProperty[] properties) + where T : Pen + { + void Invalidate(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is T sender) + { + if (e.OldValue is IAffectsRender oldValue) + { + WeakEventHandlerManager.Unsubscribe( + oldValue, + nameof(oldValue.Invalidated), + sender.AffectsRenderInvalidated); + } + + if (e.NewValue is IAffectsRender newValue) + { + WeakEventHandlerManager.Subscribe( + newValue, + nameof(newValue.Invalidated), + sender.AffectsRenderInvalidated); + } + + sender.RaiseInvalidated(EventArgs.Empty); + } + } + + foreach (var property in properties) + { + property.Changed.Subscribe(Invalidate); + } + } + + /// + /// Raises the event. + /// + /// The event args. + protected void RaiseInvalidated(EventArgs e) => Invalidated?.Invoke(this, e); + + private void AffectsRenderInvalidated(object sender, EventArgs e) => RaiseInvalidated(EventArgs.Empty); } } diff --git a/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs new file mode 100644 index 0000000000..a3746f80b5 --- /dev/null +++ b/tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs @@ -0,0 +1,33 @@ +using Avalonia.Media; +using Xunit; + +namespace Avalonia.Visuals.UnitTests.Media +{ + public class PenTests + { + [Fact] + public void Changing_Thickness_Raises_Invalidated() + { + var target = new Pen(); + var raised = false; + + target.Invalidated += (s, e) => raised = true; + target.Thickness = 18; + + Assert.True(raised); + } + + [Fact] + public void Changing_Brush_Color_Raises_Invalidated() + { + var brush = new SolidColorBrush(Colors.Red); + var target = new Pen { Brush = brush }; + var raised = false; + + target.Invalidated += (s, e) => raised = true; + brush.Color = Colors.Green; + + Assert.True(raised); + } + } +}