Browse Source

Make DashStyle.Dashes an AvaloniaList.

So that it can be parsed from XAML and changes can be made.
pull/5092/head
Steven Kirk 6 years ago
parent
commit
d99512a785
  1. 75
      src/Avalonia.Visuals/Media/DashStyle.cs
  2. 18
      tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs

75
src/Avalonia.Visuals/Media/DashStyle.cs

@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Animation;
using Avalonia.Collections;
using Avalonia.Media.Immutable;
#nullable enable
namespace Avalonia.Media
{
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Animation;
using Avalonia.Media.Immutable;
/// <summary>
/// Represents the sequence of dashes and gaps that will be applied by a <see cref="Pen"/>.
/// </summary>
@ -14,8 +17,8 @@ namespace Avalonia.Media
/// <summary>
/// Defines the <see cref="Dashes"/> property.
/// </summary>
public static readonly StyledProperty<IReadOnlyList<double>> DashesProperty =
AvaloniaProperty.Register<DashStyle, IReadOnlyList<double>>(nameof(Dashes));
public static readonly StyledProperty<AvaloniaList<double>> DashesProperty =
AvaloniaProperty.Register<DashStyle, AvaloniaList<double>>(nameof(Dashes));
/// <summary>
/// Defines the <see cref="Offset"/> property.
@ -23,10 +26,10 @@ namespace Avalonia.Media
public static readonly StyledProperty<double> OffsetProperty =
AvaloniaProperty.Register<DashStyle, double>(nameof(Offset));
private static ImmutableDashStyle s_dash;
private static ImmutableDashStyle s_dot;
private static ImmutableDashStyle s_dashDot;
private static ImmutableDashStyle s_dashDotDot;
private static ImmutableDashStyle? s_dash;
private static ImmutableDashStyle? s_dot;
private static ImmutableDashStyle? s_dashDot;
private static ImmutableDashStyle? s_dashDotDot;
/// <summary>
/// Initializes a new instance of the <see cref="DashStyle"/> class.
@ -41,9 +44,9 @@ namespace Avalonia.Media
/// </summary>
/// <param name="dashes">The dashes collection.</param>
/// <param name="offset">The dash sequence offset.</param>
public DashStyle(IEnumerable<double> dashes, double offset)
public DashStyle(IEnumerable<double>? dashes, double offset)
{
Dashes = (IReadOnlyList<double>)dashes?.ToList() ?? Array.Empty<double>();
Dashes = (dashes as AvaloniaList<double>) ?? new AvaloniaList<double>(dashes ?? Array.Empty<double>());
Offset = offset;
}
@ -61,31 +64,27 @@ namespace Avalonia.Media
/// <summary>
/// Represents a dashed <see cref="DashStyle"/>.
/// </summary>
public static IDashStyle Dash =>
s_dash ?? (s_dash = new ImmutableDashStyle(new double[] { 2, 2 }, 1));
public static IDashStyle Dash => s_dash ??= new ImmutableDashStyle(new double[] { 2, 2 }, 1);
/// <summary>
/// Represents a dotted <see cref="DashStyle"/>.
/// </summary>
public static IDashStyle Dot =>
s_dot ?? (s_dot = new ImmutableDashStyle(new double[] { 0, 2 }, 0));
public static IDashStyle Dot => s_dot ??= new ImmutableDashStyle(new double[] { 0, 2 }, 0);
/// <summary>
/// Represents a dashed dotted <see cref="DashStyle"/>.
/// </summary>
public static IDashStyle DashDot =>
s_dashDot ?? (s_dashDot = new ImmutableDashStyle(new double[] { 2, 2, 0, 2 }, 1));
public static IDashStyle DashDot => s_dashDot ??= new ImmutableDashStyle(new double[] { 2, 2, 0, 2 }, 1);
/// <summary>
/// Represents a dashed double dotted <see cref="DashStyle"/>.
/// </summary>
public static IDashStyle DashDotDot =>
s_dashDotDot ?? (s_dashDotDot = new ImmutableDashStyle(new double[] { 2, 2, 0, 2, 0, 2 }, 1));
public static IDashStyle DashDotDot => s_dashDotDot ??= new ImmutableDashStyle(new double[] { 2, 2, 0, 2, 0, 2 }, 1);
/// <summary>
/// Gets or sets the length of alternating dashes and gaps.
/// </summary>
public IReadOnlyList<double> Dashes
public AvaloniaList<double> Dashes
{
get => GetValue(DashesProperty);
set => SetValue(DashesProperty, value);
@ -100,15 +99,43 @@ namespace Avalonia.Media
set => SetValue(OffsetProperty, value);
}
IReadOnlyList<double> IDashStyle.Dashes => Dashes;
/// <summary>
/// Raised when the dash style changes.
/// </summary>
public event EventHandler Invalidated;
public event EventHandler? Invalidated;
/// <summary>
/// Returns an immutable clone of the <see cref="DashStyle"/>.
/// </summary>
/// <returns></returns>
public ImmutableDashStyle ToImmutable() => new ImmutableDashStyle(Dashes, Offset);
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == DashesProperty)
{
var oldValue = change.OldValue.GetValueOrDefault<AvaloniaList<double>>();
var newValue = change.NewValue.GetValueOrDefault<AvaloniaList<double>>();
if (oldValue is object)
{
oldValue.CollectionChanged -= DashesChanged;
}
if (newValue is object)
{
newValue.CollectionChanged += DashesChanged;
}
}
}
private void DashesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Invalidated?.Invoke(this, e);
}
}
}

18
tests/Avalonia.Visuals.UnitTests/Media/PenTests.cs

@ -1,4 +1,5 @@
using Avalonia.Media;
using Avalonia.Collections;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Xunit;
@ -39,7 +40,20 @@ namespace Avalonia.Visuals.UnitTests.Media
var raised = false;
target.Invalidated += (s, e) => raised = true;
dashes.Dashes = new[] { 0.1, 0.2 };
dashes.Dashes = new AvaloniaList<double> { 0.1, 0.2 };
Assert.True(raised);
}
[Fact]
public void Adding_DashStyle_Dashes_Raises_Invalidated()
{
var dashes = new DashStyle();
var target = new Pen { DashStyle = dashes };
var raised = false;
target.Invalidated += (s, e) => raised = true;
dashes.Dashes.Add(0.3);
Assert.True(raised);
}

Loading…
Cancel
Save