Example #1
0
 public ChatTableRow(User user, string message, DateTime messageDate, LobbyMessageType messageType)
 {
     this.InitializeComponent();
     this.User = user;
     this.Message = message;
     this.MessageDate = messageDate;
     this.MessageType = messageType;
     this.Unloaded += OnUnloaded;
     this.Loaded += OnLoaded;
     this.UsernameParagraph.Inlines.Add(new Run());
     enableGifs = Prefs.EnableChatGifs;
     enableImages = Prefs.EnableChatImages;
 }
Example #2
0
 public ChatTableRow(User user, string id, string message, DateTime messageDate, LobbyMessageType messageType)
 {
     this.InitializeComponent();
     this.Id = id;
     this.User = user;
     this.Message = message;
     this.MessageDate = messageDate;
     this.MessageType = messageType;
     this.Unloaded += OnUnloaded;
     this.Loaded += OnLoaded;
     enableGifs = Prefs.EnableChatGifs;
     enableImages = Prefs.EnableChatImages;
 }
Example #3
0
 public ChatTableRow(User user, string message, DateTime messageDate, LobbyMessageType messageType)
 {
     this.InitializeComponent();
     this.User        = user;
     this.Message     = message;
     this.MessageDate = messageDate;
     this.MessageType = messageType;
     this.Unloaded   += OnUnloaded;
     this.Loaded     += OnLoaded;
     this.UsernameParagraph.Inlines.Add(new Run());
     enableGifs   = Prefs.EnableChatGifs;
     enableImages = Prefs.EnableChatImages;
 }
Example #4
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom = from;
            var theMessage = message;
            var therTime = receiveTime;
            var themType = messageType;
            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }
            if (theFrom.UserName.Equals("octgn-gap", StringComparison.InvariantCultureIgnoreCase))
            {
                var cl = theMessage.IndexOf(':');
                theFrom.UserName = "******" + theMessage.Substring(0, cl) + "]";
                theMessage = theMessage.Substring(cl + 1, theMessage.Length - cl - 1).Trim();
            }

            if (theMessage.ToLowerInvariant().Contains("@" + Program.LobbyClient.Me.UserName.ToLowerInvariant()))
            {
                Sounds.PlayMessageSound();
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
                    {
                        // Got mostly from http://stackoverflow.com/questions/13456441/wpf-richtextboxs-conditionally-scroll
                        var rtbatbottom = false;

                        var offset = Chat.VerticalOffset + Chat.ViewportHeight;
                        if (Math.Abs(offset - Chat.ExtentHeight) <= double.Epsilon)
                        {
                            rtbatbottom = true;
                            justScrolledToBottom = false;
                            //Chat.ScrollToEnd();
                        }
                        else
                        {
                            var contentIsLargerThatViewport = Chat.ExtentHeight > Chat.ViewportHeight;
                            if (Math.Abs(Chat.VerticalOffset - 0) < double.Epsilon && contentIsLargerThatViewport)
                            {
                                rtbatbottom = true;
                                justScrolledToBottom = false;
                                //Chat.ScrollToEnd();
                            }
                            else
                            {
                                if (!justScrolledToBottom)
                                {
                                    var missed = new MissedMessagesBreak();
                                    ChatRowGroup.Rows.Add(missed);
                                    justScrolledToBottom = true;
                                }
                            }
                        }

                        //if (Math.Abs(dVer - 0) > double.Epsilon)
                        //{
                        //    if (Math.Abs(dVer + dViewport - dExtent) < double.Epsilon)
                        //    {
                        //        rtbatbottom = true;
                        //        justScrolledToBottom = false;
                        //    }
                        //    else
                        //    {
                        //        if (!justScrolledToBottom)
                        //        {
                        //            var missed = new MissedMessagesBreak();
                        //            ChatRowGroup.Rows.Add(missed);
                        //            justScrolledToBottom = true;
                        //        }
                        //    }
                        //}

                        var ctr = new ChatTableRow(theFrom, theMessage, therTime, themType);
                        //var ctr = new ChatTableRow { User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType };

                        ctr.OnMouseUsernameEnter += ChatTableRow_MouseEnter;
                        ctr.OnMouseUsernameLeave += ChatTableRow_MouseLeave;
                        ChatRowGroup.Rows.Add(ctr);
                        if (rtbatbottom)
                        {
                            Chat.ScrollToEnd();
                        }
                        if (ChatRowGroup.Rows.Count > Prefs.MaxChatHistory)
                        {
                            var remlist =
                                ChatRowGroup.Rows.Take(ChatRowGroup.Rows.Count - Prefs.MaxChatHistory).ToArray();
                            foreach (var r in remlist)
                            {
                                ChatRowGroup.Rows.Remove(r);
                            }
                        }
                    }));
        }
Example #5
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="id">The message Id</param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, string id, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom    = from;
            var theMessage = message;
            var therTime   = receiveTime;
            var themType   = messageType;
            var theId      = id;

            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }
            if (theFrom.UserName.Equals("octgn-gap", StringComparison.InvariantCultureIgnoreCase))
            {
                var cl = theMessage.IndexOf(':');
                theFrom.UserName = "******" + theMessage.Substring(0, cl) + "]";
                theMessage       = theMessage.Substring(cl + 1, theMessage.Length - cl - 1).Trim();
            }

            if (theMessage.ToLowerInvariant().Contains(Program.LobbyClient.Me.UserName.ToLowerInvariant()))
            {
                Sounds.PlayMessageSound();
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
            {
                // Got mostly from http://stackoverflow.com/questions/13456441/wpf-richtextboxs-conditionally-scroll
                keepScrolledToBottom = false;

                var offset = Chat.VerticalOffset + Chat.ViewportHeight;
                // How far the scroll bar is up from the bottom
                if (Math.Abs(offset - Chat.ExtentHeight) <= 15)
                {
                    // We should auto scroll
                    keepScrolledToBottom = true;
                    this.shouldDisplayMissedMessagesBreak = false;
                    //Chat.ScrollToEnd();
                }
                else
                {
                    var contentIsLargerThatViewport = Chat.ExtentHeight > Chat.ViewportHeight;
                    // How far the scroll bar is up from the bottom
                    if (Math.Abs(Chat.VerticalOffset - 0) < 15 && contentIsLargerThatViewport)
                    {
                        // We should auto scroll
                        keepScrolledToBottom = true;
                        this.shouldDisplayMissedMessagesBreak = false;
                        //Chat.ScrollToEnd();
                    }
                    else
                    {
                        // We shouldn't auto scroll, instead show the missed message thingy
                        if (!this.shouldDisplayMissedMessagesBreak)
                        {
                            var missed = new MissedMessagesBreak();
                            ChatRowGroup.Rows.Add(missed);
                            this.shouldDisplayMissedMessagesBreak = true;
                        }
                    }
                }

                var ctr = new ChatTableRow(theFrom, theId, theMessage, therTime, themType);
                //var ctr = new ChatTableRow { User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType };

                ctr.OnMouseUsernameEnter += ChatTableRow_MouseEnter;
                ctr.OnMouseUsernameLeave += ChatTableRow_MouseLeave;
                ChatRowGroup.Rows.Add(ctr);
                if (ChatRowGroup.Rows.Count > Prefs.MaxChatHistory)
                {
                    var remlist =
                        ChatRowGroup.Rows.Take(ChatRowGroup.Rows.Count - Prefs.MaxChatHistory).ToArray();
                    foreach (var r in remlist)
                    {
                        ChatRowGroup.Rows.Remove(r);
                    }
                }
            }));
            Dispatcher.BeginInvoke(new Action(
                                       () =>
            {
                if (keepScrolledToBottom && IsLoadingHistory == false)
                {
                    Chat.ScrollToEnd();
                }
            }));
        }
Example #6
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom = from;
            var theMessage = message;
            var therTime = receiveTime;
            var themType = messageType;
            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
                    {
                        var rtbatbottom = false;

                        // bool firstAutoScroll = true; // never used
                        //Chat.ScrollToVerticalOffset(Chat.VerticalOffset);

                        // check to see if the richtextbox is scrolled to the bottom.
                        var dVer = Chat.VerticalOffset;

                        // get the vertical size of the scrollable content area
                        var dViewport = Chat.ViewportHeight;

                        // get the vertical size of the visible content area
                        var dExtent = Chat.ExtentHeight;

                        if (Math.Abs(dVer - 0) < double.Epsilon && dViewport < dExtent)
                        {
                            rtbatbottom = true;
                        }

                        if (Math.Abs(dVer - 0) > double.Epsilon)
                        {
                            if (Math.Abs(dVer + dViewport - dExtent) < double.Epsilon)
                            {
                                rtbatbottom = true;
                                justScrolledToBottom = false;
                            }
                            else
                            {
                                if (!justScrolledToBottom)
                                {
                                    var tr = new TableRow();
                                    var tc = new TableCell() { BorderThickness = new Thickness(0, 1, 0, 1), BorderBrush = Brushes.Gainsboro, ColumnSpan = 3 };
                                    tr.Cells.Add(tc);
                                    ChatRowGroup.Rows.Add(tr);
                                    justScrolledToBottom = true;
                                }
                            }
                        }

                        var ctr = new ChatTableRow(theFrom, theMessage, therTime, themType);
                        //var ctr = new ChatTableRow { User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType };

                        ctr.OnMouseUsernameEnter += ChatTableRow_MouseEnter;
                        ctr.OnMouseUsernameLeave += ChatTableRow_MouseLeave;
                        ChatRowGroup.Rows.Add(ctr);
                        if (rtbatbottom)
                        {
                            Chat.ScrollToEnd();
                        }
                        if (ChatRowGroup.Rows.Count > Prefs.MaxChatHistory)
                        {
                            var remlist =
                                ChatRowGroup.Rows.Where(x=>x is ChatTableRow).Cast<ChatTableRow>()
                                            .OrderBy(x => x.MessageDate)
                                            .Take(ChatRowGroup.Rows.Count - 50).ToArray();
                            foreach (var r in remlist)
                            {
                                ChatRowGroup.Rows.Remove(r);
                            }
                        }
                    }));
        }
Example #7
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="id">The message Id</param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, string id, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom    = from;
            var theMessage = message;
            var therTime   = receiveTime;
            var themType   = messageType;
            var theId      = id;

            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }
            if (theFrom.UserName.Equals("octgn-gap", StringComparison.InvariantCultureIgnoreCase))
            {
                var cl = theMessage.IndexOf(':');
                theFrom.UserName = "******" + theMessage.Substring(0, cl) + "]";
                theMessage       = theMessage.Substring(cl + 1, theMessage.Length - cl - 1).Trim();
            }

            if (theMessage.ToLowerInvariant().Contains("@" + Program.LobbyClient.Me.UserName.ToLowerInvariant()))
            {
                Sounds.PlayMessageSound();
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
            {
                // Got mostly from http://stackoverflow.com/questions/13456441/wpf-richtextboxs-conditionally-scroll
                var rtbatbottom = false;

                var offset = Chat.VerticalOffset + Chat.ViewportHeight;
                if (Math.Abs(offset - Chat.ExtentHeight) <= double.Epsilon)
                {
                    rtbatbottom          = true;
                    justScrolledToBottom = false;
                    //Chat.ScrollToEnd();
                }
                else
                {
                    var contentIsLargerThatViewport = Chat.ExtentHeight > Chat.ViewportHeight;
                    if (Math.Abs(Chat.VerticalOffset - 0) < double.Epsilon && contentIsLargerThatViewport)
                    {
                        rtbatbottom          = true;
                        justScrolledToBottom = false;
                        //Chat.ScrollToEnd();
                    }
                    else
                    {
                        if (!justScrolledToBottom)
                        {
                            var missed = new MissedMessagesBreak();
                            ChatRowGroup.Rows.Add(missed);
                            justScrolledToBottom = true;
                        }
                    }
                }

                //if (Math.Abs(dVer - 0) > double.Epsilon)
                //{
                //    if (Math.Abs(dVer + dViewport - dExtent) < double.Epsilon)
                //    {
                //        rtbatbottom = true;
                //        justScrolledToBottom = false;
                //    }
                //    else
                //    {
                //        if (!justScrolledToBottom)
                //        {
                //            var missed = new MissedMessagesBreak();
                //            ChatRowGroup.Rows.Add(missed);
                //            justScrolledToBottom = true;
                //        }
                //    }
                //}

                //if (
                //    ChatRowGroup.Rows.OfType<ChatTableRow>()
                //        .Any(x =>
                //            x.Id != null
                //            && x.Id.Equals(theId, StringComparison.InvariantCultureIgnoreCase)
                //            && x.Message.Equals(message)
                //        ))
                //{
                //    return;
                //}
                var ctr = new ChatTableRow(theFrom, theId, theMessage, therTime, themType);
                //var ctr = new ChatTableRow { User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType };

                ctr.OnMouseUsernameEnter += ChatTableRow_MouseEnter;
                ctr.OnMouseUsernameLeave += ChatTableRow_MouseLeave;
                ChatRowGroup.Rows.Add(ctr);
                if (rtbatbottom)
                {
                    Chat.ScrollToEnd();
                }
                if (ChatRowGroup.Rows.Count > Prefs.MaxChatHistory)
                {
                    var remlist =
                        ChatRowGroup.Rows.Take(ChatRowGroup.Rows.Count - Prefs.MaxChatHistory).ToArray();
                    foreach (var r in remlist)
                    {
                        ChatRowGroup.Rows.Remove(r);
                    }
                }
            }));
        }
Example #8
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom = from;
            var theMessage = message;
            var therTime = receiveTime;
            var themType = messageType;
            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
                    {
                        var rtbatbottom = false;

                        // bool firstAutoScroll = true; // never used
                        Chat.ScrollToVerticalOffset(Chat.VerticalOffset);

                        // check to see if the richtextbox is scrolled to the bottom.
                        var dVer = Chat.VerticalOffset;

                        // get the vertical size of the scrollable content area
                        var dViewport = Chat.ViewportHeight;

                        // get the vertical size of the visible content area
                        var dExtent = Chat.ExtentHeight;

                        if (Math.Abs(dVer - 0) < double.Epsilon && dViewport < dExtent)
                        {
                            rtbatbottom = true;
                        }

                        if (Math.Abs(dVer - 0) > double.Epsilon)
                        {
                            if (Math.Abs(dVer + dViewport - dExtent) < double.Epsilon)
                            {
                                rtbatbottom = true;
                                justScrolledToBottom = false;
                            }
                            else
                            {
                                if (!justScrolledToBottom)
                                {
                                    var tr = new TableRow();
                                    var tc = new TableCell() { BorderThickness = new Thickness(0, 1, 0, 1), BorderBrush = Brushes.Gainsboro, ColumnSpan = 3 };
                                    tr.Cells.Add(tc);
                                    ChatRowGroup.Rows.Add(tr);
                                    justScrolledToBottom = true;
                                }
                            }
                        }

                        var ctr = new ChatTableRow { User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType };

                        ctr.MouseEnter += (o, args) =>
                        {
                            foreach (var r in ChatRowGroup.Rows)
                            {
                                var rr = r as ChatTableRow;
                                if (rr == null)
                                {
                                    continue;
                                }

                                if (rr.User.UserName
                                    == theFrom.UserName)
                                {
                                    r.Background = this.HoverBackBrush;
                                }
                            }
                        };
                        ctr.MouseLeave += (o, args) =>
                        {
                            foreach (var r in ChatRowGroup.Rows)
                            {
                                r.Background = null;
                            }
                        };
                        ChatRowGroup.Rows.Add(ctr);
                        if (rtbatbottom)
                        {
                            Chat.ScrollToEnd();
                        }
                    }));
        }
Example #9
0
 public ChatTableRow(User user, string id, string message, DateTime messageDate, LobbyMessageType messageType)
 {
     this.InitializeComponent();
     this.Id          = id;
     this.User        = user;
     this.Message     = message;
     this.MessageDate = messageDate;
     this.MessageType = messageType;
     this.Unloaded   += OnUnloaded;
     this.Loaded     += OnLoaded;
     enableGifs       = Prefs.EnableChatGifs;
     enableImages     = Prefs.EnableChatImages;
 }
Example #10
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom    = from;
            var theMessage = message;
            var therTime   = receiveTime;
            var themType   = messageType;

            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
            {
                var rtbatbottom = false;

                // bool firstAutoScroll = true; // never used
                Chat.ScrollToVerticalOffset(Chat.VerticalOffset);

                // check to see if the richtextbox is scrolled to the bottom.
                var dVer = Chat.VerticalOffset;

                // get the vertical size of the scrollable content area
                var dViewport = Chat.ViewportHeight;

                // get the vertical size of the visible content area
                var dExtent = Chat.ExtentHeight;

                if (Math.Abs(dVer - 0) < double.Epsilon && dViewport < dExtent)
                {
                    rtbatbottom = true;
                }

                if (Math.Abs(dVer - 0) > double.Epsilon)
                {
                    if (Math.Abs(dVer + dViewport - dExtent) < double.Epsilon)
                    {
                        rtbatbottom          = true;
                        justScrolledToBottom = false;
                    }
                    else
                    {
                        if (!justScrolledToBottom)
                        {
                            var tr = new TableRow();
                            var tc = new TableCell()
                            {
                                BorderThickness = new Thickness(0, 1, 0, 1), BorderBrush = Brushes.Gainsboro, ColumnSpan = 3
                            };
                            tr.Cells.Add(tc);
                            ChatRowGroup.Rows.Add(tr);
                            justScrolledToBottom = true;
                        }
                    }
                }

                var ctr = new ChatTableRow {
                    User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType
                };

                ctr.MouseEnter += (o, args) =>
                {
                    foreach (var r in ChatRowGroup.Rows)
                    {
                        var rr = r as ChatTableRow;
                        if (rr == null)
                        {
                            continue;
                        }

                        if (rr.User.UserName
                            == theFrom.UserName)
                        {
                            r.Background = this.HoverBackBrush;
                        }
                    }
                };
                ctr.MouseLeave += (o, args) =>
                {
                    foreach (var r in ChatRowGroup.Rows)
                    {
                        r.Background = null;
                    }
                };
                ChatRowGroup.Rows.Add(ctr);
                if (rtbatbottom)
                {
                    Chat.ScrollToEnd();
                }
            }));
        }
Example #11
0
        /// <summary>
        /// When a message is received in the room.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="from">
        /// The from.
        /// </param>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="receiveTime">
        /// The receive Time.
        /// </param>
        /// <param name="messageType">
        /// The message type.
        /// </param>
        private void RoomOnMessageReceived(object sender, User @from, string message, DateTime receiveTime, LobbyMessageType messageType)
        {
            var theFrom    = from;
            var theMessage = message;
            var therTime   = receiveTime;
            var themType   = messageType;

            if (string.IsNullOrWhiteSpace(theFrom.UserName))
            {
                theFrom.UserName = "******";
            }

            if (message.ToLowerInvariant().Contains("@" + Program.LobbyClient.Me.UserName.ToLowerInvariant()))
            {
                Sounds.PlayMessageSound();
            }

            Dispatcher.Invoke(
                new Action(
                    () =>
            {
                var rtbatbottom = false;

                // bool firstAutoScroll = true; // never used
                //Chat.ScrollToVerticalOffset(Chat.VerticalOffset);

                // check to see if the richtextbox is scrolled to the bottom.
                var dVer = Chat.VerticalOffset;

                // get the vertical size of the scrollable content area
                var dViewport = Chat.ViewportHeight;

                // get the vertical size of the visible content area
                var dExtent = Chat.ExtentHeight;

                if (Math.Abs(dVer - 0) < double.Epsilon && dViewport < dExtent)
                {
                    rtbatbottom = true;
                }

                if (Math.Abs(dVer - 0) > double.Epsilon)
                {
                    if (Math.Abs(dVer + dViewport - dExtent) < double.Epsilon)
                    {
                        rtbatbottom          = true;
                        justScrolledToBottom = false;
                    }
                    else
                    {
                        if (!justScrolledToBottom)
                        {
                            var tr = new TableRow();
                            var tc = new TableCell()
                            {
                                BorderThickness = new Thickness(0, 1, 0, 1), BorderBrush = Brushes.Gainsboro, ColumnSpan = 3
                            };
                            tr.Cells.Add(tc);
                            ChatRowGroup.Rows.Add(tr);
                            justScrolledToBottom = true;
                        }
                    }
                }

                var ctr = new ChatTableRow(theFrom, theMessage, therTime, themType);
                //var ctr = new ChatTableRow { User = theFrom, Message = theMessage, MessageDate = therTime, MessageType = themType };

                ctr.OnMouseUsernameEnter += ChatTableRow_MouseEnter;
                ctr.OnMouseUsernameLeave += ChatTableRow_MouseLeave;
                ChatRowGroup.Rows.Add(ctr);
                if (rtbatbottom)
                {
                    Chat.ScrollToEnd();
                }
                if (ChatRowGroup.Rows.Count > Prefs.MaxChatHistory)
                {
                    var remlist =
                        ChatRowGroup.Rows.Where(x => x is ChatTableRow).Cast <ChatTableRow>()
                        .OrderBy(x => x.MessageDate)
                        .Take(ChatRowGroup.Rows.Count - 50).ToArray();
                    foreach (var r in remlist)
                    {
                        ChatRowGroup.Rows.Remove(r);
                    }
                }
            }));
        }