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;
}
}