using System.ComponentModel; using TinyChat.Messages.Formatting; namespace TinyChat; /// /// A panel control that displays a chat message with sender name and content. /// public class ChatMessageControl : Panel, IChatMessageControl { private IChatMessage? _message; private bool _isReceivingStream; private readonly Label _senderLabel; private readonly Label _messageLabel; /// /// The event that is raised when the size of the control is updated while streaming a message. /// public event EventHandler? SizeUpdatedWhileStreaming; /// /// Gets or sets the formatter that converts message content into displayable strings. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public required IMessageFormatter MessageFormatter { get; set; } /// /// Initializes a new instance of the class. /// public ChatMessageControl() { _senderLabel = new Label() { Dock = DockStyle.Top, AutoSize = true, Font = new Font(Font, FontStyle.Bold), UseMnemonic = false }; _messageLabel = new Label() { Dock = DockStyle.Fill, AutoSize = true, UseMnemonic = false }; Controls.Add(_senderLabel); Controls.Add(_messageLabel); _messageLabel.BringToFront(); AutoSize = true; Padding = new Padding(8); } /// /// Gets or sets the chat message displayed by this control. /// When set, the control updates to display the sender's name and message content. /// If the message is null, both the sender and content labels will display empty strings. /// /// /// The instance to display, or null to clear the display. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public IChatMessage? Message { get => _message; set { _message = value; _senderLabel.Text = Message?.Sender?.Name ?? string.Empty; _messageLabel.DataBindings.Clear(); if (Message is not null) { var binding = _messageLabel.DataBindings.Add(nameof(_messageLabel.Text), Message.Content, nameof(Message.Content.Content)); binding.Format += (_, e) => e.Value = MessageFormatter.Format(new StringMessageContent(e.Value?.ToString() ?? string.Empty)); } } } /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public override Size MaximumSize { get => base.MaximumSize; set { base.MaximumSize = value; _senderLabel.MaximumSize = new Size(value.Width - Padding.Horizontal, 0); _messageLabel.MaximumSize = new Size(value.Width - Padding.Horizontal, 0); } } /// protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); if (_isReceivingStream) SizeUpdatedWhileStreaming?.Invoke(this, EventArgs.Empty); } /// void IChatMessageControl.SetIsReceivingStream(bool isReceiving) { _isReceivingStream = isReceiving; } }