// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Collections; using Avalonia.Metadata; using Avalonia.Platform; using System; namespace Avalonia.Media { public class PathGeometry : StreamGeometry { /// /// Defines the property. /// public static readonly DirectProperty FiguresProperty = AvaloniaProperty.RegisterDirect(nameof(Figures), g => g.Figures, (g, f) => g.Figures = f); /// /// Defines the property. /// public static readonly StyledProperty FillRuleProperty = AvaloniaProperty.Register(nameof(FillRule)); static PathGeometry() { FiguresProperty.Changed.Subscribe(onNext: v => { (v.Sender as PathGeometry)?.OnFiguresChanged(v.OldValue as PathFigures, v.NewValue as PathFigures); }); } /// /// Initializes a new instance of the class. /// public PathGeometry() { Figures = new PathFigures(); } /// /// Gets or sets the figures. /// /// /// The figures. /// [Content] public PathFigures Figures { get { return _figures; } set { SetAndRaise(FiguresProperty, ref _figures, value); } } /// /// Gets or sets the fill rule. /// /// /// The fill rule. /// public FillRule FillRule { get { return GetValue(FillRuleProperty); } set { SetValue(FillRuleProperty, value); } } public override IGeometryImpl PlatformImpl { get { PrepareIfNeeded(); return base.PlatformImpl; } protected set { base.PlatformImpl = value; } } public override Geometry Clone() { PrepareIfNeeded(); return base.Clone(); } public void PrepareIfNeeded() { if (_isDirty) { _isDirty = false; using (var ctx = Open()) { ctx.SetFillRule(FillRule); foreach (var f in Figures) { f.ApplyTo(ctx); } } } } internal void NotifyChanged() { _isDirty = true; } private PathFigures _figures; private IDisposable _figuresObserver = null; private IDisposable _figuresPropertiesObserver = null; private bool _isDirty = true; private void OnFiguresChanged(PathFigures oldValue, PathFigures newValue) { _figuresObserver?.Dispose(); _figuresPropertiesObserver?.Dispose(); _figuresObserver = newValue?.ForEachItem(f => NotifyChanged(), f => NotifyChanged(), () => NotifyChanged()); _figuresPropertiesObserver = newValue?.TrackItemPropertyChanged(t => NotifyChanged()); } } }