|
|
@@ -3,10 +3,9 @@
|
|
|
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
-using System.Linq;
|
|
|
-using System.Text;
|
|
|
-using System.Threading.Tasks;
|
|
|
using Avalonia.Platform;
|
|
|
+using Avalonia.Metadata;
|
|
|
+using Avalonia.Collections;
|
|
|
|
|
|
namespace Avalonia.Media
|
|
|
{
|
|
|
@@ -15,36 +14,122 @@ namespace Avalonia.Media
|
|
|
/// </summary>
|
|
|
public class PolylineGeometry : Geometry
|
|
|
{
|
|
|
- private IList<Point> _points;
|
|
|
- private bool _isFilled;
|
|
|
+ /// <summary>
|
|
|
+ /// Defines the <see cref="Points"/> property.
|
|
|
+ /// </summary>
|
|
|
+ public static readonly DirectProperty<PolylineGeometry, Points> PointsProperty =
|
|
|
+ AvaloniaProperty.RegisterDirect<PolylineGeometry, Points>(nameof(Points), g => g.Points, (g, f) => g.Points = f);
|
|
|
|
|
|
- public PolylineGeometry(IList<Point> points, bool isFilled)
|
|
|
+ /// <summary>
|
|
|
+ /// Defines the <see cref="IsFilled"/> property.
|
|
|
+ /// </summary>
|
|
|
+ public static readonly AvaloniaProperty<bool> IsFilledProperty =
|
|
|
+ AvaloniaProperty.Register<PolylineGeometry, bool>(nameof(IsFilled));
|
|
|
+
|
|
|
+ static PolylineGeometry()
|
|
|
+ {
|
|
|
+ PointsProperty.Changed.Subscribe(onNext: v =>
|
|
|
+ {
|
|
|
+ (v.Sender as PolylineGeometry)?.OnPointsChanged(v.OldValue as Points, v.NewValue as Points);
|
|
|
+ });
|
|
|
+ IsFilledProperty.Changed.AddClassHandler<PolylineGeometry>(x => a => x.NotifyChanged());
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Initializes a new instance of the <see cref="PolylineGeometry"/> class.
|
|
|
+ /// </summary>
|
|
|
+ public PolylineGeometry()
|
|
|
{
|
|
|
- _points = points;
|
|
|
- _isFilled = isFilled;
|
|
|
IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
|
|
|
- IStreamGeometryImpl impl = factory.CreateStreamGeometry();
|
|
|
+ PlatformImpl = factory.CreateStreamGeometry();
|
|
|
+
|
|
|
+ Points = new Points();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Initializes a new instance of the <see cref="PolylineGeometry"/> class.
|
|
|
+ /// </summary>
|
|
|
+ public PolylineGeometry(IEnumerable<Point> points, bool isFilled) : this()
|
|
|
+ {
|
|
|
+ Points.AddRange(points);
|
|
|
+ IsFilled = isFilled;
|
|
|
+
|
|
|
+ PrepareIfNeeded();
|
|
|
+ }
|
|
|
|
|
|
- using (IStreamGeometryContextImpl context = impl.Open())
|
|
|
+ public void PrepareIfNeeded()
|
|
|
+ {
|
|
|
+ if (_isDirty)
|
|
|
{
|
|
|
- if (points.Count > 0)
|
|
|
+ _isDirty = false;
|
|
|
+
|
|
|
+ using (var context = ((IStreamGeometryImpl)PlatformImpl).Open())
|
|
|
{
|
|
|
- context.BeginFigure(points[0], isFilled);
|
|
|
- for (int i = 1; i < points.Count; i++)
|
|
|
+ var points = Points;
|
|
|
+ var isFilled = IsFilled;
|
|
|
+ if (points.Count > 0)
|
|
|
{
|
|
|
- context.LineTo(points[i]);
|
|
|
+ context.BeginFigure(points[0], isFilled);
|
|
|
+ for (int i = 1; i < points.Count; i++)
|
|
|
+ {
|
|
|
+ context.LineTo(points[i]);
|
|
|
+ }
|
|
|
+ context.EndFigure(isFilled);
|
|
|
}
|
|
|
- context.EndFigure(isFilled);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- PlatformImpl = impl;
|
|
|
+ /// <summary>
|
|
|
+ /// Gets or sets the figures.
|
|
|
+ /// </summary>
|
|
|
+ /// <value>
|
|
|
+ /// The points.
|
|
|
+ /// </value>
|
|
|
+ [Content]
|
|
|
+ public Points Points
|
|
|
+ {
|
|
|
+ get => _points;
|
|
|
+ set => SetAndRaise(PointsProperty, ref _points, value);
|
|
|
}
|
|
|
|
|
|
+ public bool IsFilled
|
|
|
+ {
|
|
|
+ get => GetValue(IsFilledProperty);
|
|
|
+ set => SetValue(IsFilledProperty, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override IGeometryImpl PlatformImpl
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ PrepareIfNeeded();
|
|
|
+ return base.PlatformImpl;
|
|
|
+ }
|
|
|
+ protected set => base.PlatformImpl = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Points _points;
|
|
|
+ private bool _isDirty;
|
|
|
+ private IDisposable _pointsObserver;
|
|
|
+
|
|
|
/// <inheritdoc/>
|
|
|
public override Geometry Clone()
|
|
|
{
|
|
|
- return new PolylineGeometry(new List<Point>(_points), _isFilled);
|
|
|
+ PrepareIfNeeded();
|
|
|
+ return new PolylineGeometry(Points, IsFilled);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnPointsChanged(Points oldValue, Points newValue)
|
|
|
+ {
|
|
|
+ _pointsObserver?.Dispose();
|
|
|
+
|
|
|
+ _pointsObserver = newValue?.ForEachItem(f => NotifyChanged(), f => NotifyChanged(), () => NotifyChanged());
|
|
|
+ }
|
|
|
+
|
|
|
+ internal void NotifyChanged()
|
|
|
+ {
|
|
|
+ _isDirty = true;
|
|
|
}
|
|
|
}
|
|
|
}
|