using System; using System.Text; using Avalonia.Collections; using Avalonia.LogicalTree; using Avalonia.Metadata; namespace Avalonia.Controls.Documents { /// /// A collection of s. /// [WhitespaceSignificantCollection] public class InlineCollection : AvaloniaList { private ILogical? _parent; private IInlineHost? _inlineHost; private string? _text = string.Empty; /// /// Initializes a new instance of the class. /// public InlineCollection() { ResetBehavior = ResetBehavior.Remove; this.ForEachItem( x => { ((ISetLogicalParent)x).SetParent(Parent); x.InlineHost = InlineHost; Invalidate(); }, x => { ((ISetLogicalParent)x).SetParent(null); x.InlineHost = InlineHost; Invalidate(); }, () => throw new NotSupportedException()); } internal ILogical? Parent { get => _parent; set { _parent = value; OnParentChanged(value); } } internal IInlineHost? InlineHost { get => _inlineHost; set { _inlineHost = value; OnInlineHostChanged(value); } } public bool HasComplexContent => Count > 0; /// /// Gets or adds the text held by the inlines collection. /// /// Can be null for complex content. /// /// public string? Text { get { if (!HasComplexContent) { return _text; } var builder = new StringBuilder(); foreach (var inline in this) { inline.AppendText(builder); } return builder.ToString(); } set { if (HasComplexContent) { Add(new Run(value)); } else { _text = value; } } } /// /// Add a text segment to the collection. /// /// For non complex content this appends the text to the end of currently held text. /// For complex content this adds a to the collection. /// /// /// public void Add(string text) { if (HasComplexContent) { Add(new Run(text)); } else { _text = text; } } public void Add(IControl child) { var implicitRun = new InlineUIContainer(child); Add(implicitRun); } public override void Add(Inline item) { if (!HasComplexContent) { if (!string.IsNullOrEmpty(_text)) { base.Add(new Run(_text)); } _text = null; } base.Add(item); } /// /// Raised when an inline in the collection changes. /// public event EventHandler? Invalidated; /// /// Raises the event. /// protected void Invalidate() { if(InlineHost != null) { InlineHost.Invalidate(); } Invalidated?.Invoke(this, EventArgs.Empty); } private void OnParentChanged(ILogical? parent) { foreach(var child in this) { ((ISetLogicalParent)child).SetParent(parent); } } private void OnInlineHostChanged(IInlineHost? inlineHost) { foreach (var child in this) { child.InlineHost = inlineHost; } } } }