using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Numerics; namespace RhythmBase.Components.RichText { /// /// Represents a rich text string with various styling options. /// /// The text content of the rich string. [DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")] public struct RDPhrase(string text) : IEqualityOperators, RDPhrase, bool>, IEquatable> where TStyle : IRDRichStringStyle, new() { /// /// Gets the text content of the rich string. /// public string Text { get; internal set; } = text; /// /// Gets or sets the events associated with the rich string. /// public RDDialogueTone[] Events { get; init; } = []; /// /// Gets the length of the text content. /// /// The number of characters in the text content. public readonly int Length => Text.Length; /// /// Gets the rich string at the specified index. /// /// The index of the character. /// A new with the character at the specified index. public RDPhrase this[Index index] { get { return new RDPhrase { Text = Text[index].ToString(), Style = Style, Events = GetEvents(index.GetOffset(Length), 1) }; } } /// /// Gets the rich string within the specified range. /// /// The range of characters. /// A new with the characters within the specified range. public RDPhrase this[Range range] { get { RDPhrase style = new() { Text = Text[range], Style = Style, Events = GetEvents(range.Start.GetOffset(Length), range.End.GetOffset(Length) - range.Start.GetOffset(Length)) }; return style; } } private readonly RDDialogueTone[] GetEvents(int start, int length) => Events .Where(e => e.Index >= start && e.Index < start + length) .Select(e => new RDDialogueTone(e.Type, e.Index - start)) .ToArray(); /// /// Gets a new with the same style as the current instance. /// public TStyle Style { get; init; } = new(); /// /// Initializes a new instance of the struct with an empty text. /// public RDPhrase() : this("") { } /// /// Implicitly converts a string to an . /// /// The text to convert. /// A new instance with the specified text. public static implicit operator RDPhrase(string text) => new() { Text = text }; /// public static bool operator ==(RDPhrase left, RDPhrase right) => left.Text == right.Text && left.Style == right.Style; /// public static bool operator !=(RDPhrase left, RDPhrase right) => !(left == right); /// public readonly bool Equals(RDPhrase other) => this == other; /// public override readonly bool Equals([NotNullWhen(true)] object? obj) => obj is RDPhrase && base.Equals(obj); /// public override readonly int GetHashCode() => Text.GetHashCode(); /// public override readonly string ToString() => Text; /// private readonly string GetDebuggerDisplay() => ToString(); } }