diff --git a/ShiftOS.Frontend/Apps/ChatClient.cs b/ShiftOS.Frontend/Apps/ChatClient.cs new file mode 100644 index 0000000..de9d80f --- /dev/null +++ b/ShiftOS.Frontend/Apps/ChatClient.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ShiftOS.Engine; +using ShiftOS.Frontend.GUI; +using ShiftOS.Objects.ShiftFS; +using ShiftOS.Objects; +using ShiftOS.Frontend.GraphicsSubsystem; +using Microsoft.Xna.Framework; +using static ShiftOS.Engine.SkinEngine; +using System.Text.RegularExpressions; + +namespace ShiftOS.Frontend.Apps +{ + [WinOpen("irc")] + [DefaultTitle("IRC Client")] + [Launcher("IRC Client", false, null, "Networking")] + public class ChatClient : Control, IShiftOSWindow + { + private TextControl _sendprompt = null; + private TextInput _input = null; + private Button _send = null; + private List _messages = new List(); + + + + public ChatClient() + { + _messages.Add(new ChatMessage + { + Timestamp = DateTime.Now, + Author = "michael", + Message = "Welcome to ShiftOS IRC! Type in the box below to type a message." + }); + _send = new GUI.Button(); + _input = new GUI.TextInput(); + _sendprompt = new GUI.TextControl(); + _sendprompt.Text = "Send message:"; + _sendprompt.AutoSize = true; + _send.Text = "Send"; + _send.AutoSize = true; + AddControl(_send); + AddControl(_sendprompt); + AddControl(_input); + + _input.KeyEvent += (key) => + { + if(key.Key == Microsoft.Xna.Framework.Input.Keys.Enter && !string.IsNullOrWhiteSpace(_input.Text)) + { + SendMessage(); + } + }; + _send.Click += () => + { + if (!string.IsNullOrWhiteSpace(_input.Text)) + { + SendMessage(); + } + + }; + } + + protected override void OnLayout(GameTime gameTime) + { + _send.X = Width - _send.Width - 10; + _send.Y = Height - _send.Height - 10; + _sendprompt.X = 10; + _sendprompt.Y = _send.Y + ((_send.Height - _sendprompt.Height) / 2); + _input.Height = 24; + _input.Y = _send.Y + ((_send.Height - _input.Height) / 2); + _input.X = _sendprompt.X + _sendprompt.Width + 10; + int inRight = (Width - _send.Width - 20); + _input.AutoSize = false; + _input.Width = inRight - _input.X; + if (requiresRepaint) + { + Invalidate(); + requiresRepaint = false; + } + } + + public void SendMessage() + { + _messages.Add(new Apps.ChatMessage + { + Timestamp = DateTime.Now, + Author = SaveSystem.CurrentSave.Username, + Message = _input.Text + }); + _input.Text = ""; + + //Let's try the AI stuff... :P + if (!messagecache.Contains(_messages.Last().Message)) + messagecache.Add(_messages.Last().Message); + var rmsg = messagecache[rnd.Next(messagecache.Count)]; + var split = new List(rmsg.Split(' ')); + List nmsg = new List(); + if (split.Count > 2) + { + int amount = rnd.Next(2, 50); + for (int i = 0; i < amount; i++) + { + nmsg.Add(split[rnd.Next(split.Count)]); + } + } + else if (split.Count < 6) + { + for (int i = 0; i < rnd.Next(2); i++) + { + split.RemoveAt(i); + } + split.AddRange(Regex.Split(Regex.Replace(messagecache[rnd.Next(messagecache.Count)], "debugbot", outcomes[rnd.Next(outcomes.Length)], RegexOptions.IgnoreCase), " ")); + } + split.RemoveAt(rnd.Next(split.Count)); + split.Add(Regex.Replace(messagecache[rnd.Next(messagecache.Count)], "debugbot", outcomes[rnd.Next(outcomes.Length)], RegexOptions.IgnoreCase)); + string combinedResult = string.Join(" ", split); + _messages.Add(new ChatMessage + { + Timestamp = DateTime.Now, + Author = "debugbot", + Message = combinedResult + }); + + } + + readonly string[] outcomes = new string[] { "ok", "sure", "yeah", "yes", "no", "nope", "alright" }; + Random rnd = new Random(); + List messagecache = new List(); + + public void SendClientMessage(string nick, string message) + { + _messages.Add(new Apps.ChatMessage + { + Timestamp = DateTime.Now, + Author = nick, + Message = message + }); + Invalidate(); + } + + int vertSeparatorLeft = 20; + bool requiresRepaint = false; + + protected override void OnPaint(GraphicsContext gfx) + { + int _bottomseparator = _send.Y - 10; + gfx.DrawRectangle(0, _bottomseparator, Width, 1, UIManager.SkinTextures["ControlTextColor"]); + int nnGap = 25; + int messagebottom = _bottomseparator - 5; + foreach (var msg in _messages.OrderByDescending(x=>x.Timestamp)) + { + if (Height - messagebottom <= 0) + break; + var tsProper = $"[{msg.Timestamp.Hour.ToString("##")}:{msg.Timestamp.Minute.ToString("##")}]"; + var nnProper = $"<{msg.Author}>"; + var tsMeasure = gfx.MeasureString(tsProper, LoadedSkin.TerminalFont); + var nnMeasure = gfx.MeasureString(nnProper, LoadedSkin.TerminalFont); + int old = vertSeparatorLeft; + vertSeparatorLeft = (int)Math.Round(Math.Max(vertSeparatorLeft, tsMeasure.X + nnGap + nnMeasure.X+2)); + if (old != vertSeparatorLeft) + requiresRepaint = true; + var msgMeasure = gfx.MeasureString(msg.Message, LoadedSkin.TerminalFont, Width - vertSeparatorLeft - 4); + messagebottom -= (int)msgMeasure.Y; + gfx.DrawString(tsProper, 0, messagebottom, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.TerminalFont); + var nnColor = (msg.Author == SaveSystem.CurrentSave.Username) ? Color.Red : Color.LightGreen; + gfx.DrawString(nnProper, (int)tsMeasure.X + nnGap, messagebottom, nnColor, LoadedSkin.TerminalFont); + gfx.DrawString(msg.Message, vertSeparatorLeft + 4, messagebottom, LoadedSkin.ControlTextColor.ToMonoColor(), LoadedSkin.TerminalFont, Width - vertSeparatorLeft - 4); + } + gfx.DrawRectangle(vertSeparatorLeft, 0, 1, _bottomseparator, UIManager.SkinTextures["ControlTextColor"]); + } + + public void OnLoad() + { + + } + + public void OnSkinLoad() + { + } + + public bool OnUnload() + { + return true; + } + + public void OnUpgrade() + { + } + } + + public class ChatMessage + { + public DateTime Timestamp { get; set; } + public string Author { get; set; } + public string Message { get; set; } + } +} diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs index 4d05470..6941b7b 100644 --- a/ShiftOS.Frontend/GUI/Control.cs +++ b/ShiftOS.Frontend/GUI/Control.cs @@ -366,7 +366,7 @@ namespace ShiftOS.Frontend.GUI public void ClearControls() { _children.Clear(); - Invalidate(); + Invalidate(); } public Point PointToLocal(int x, int y) diff --git a/ShiftOS.Frontend/GUI/TextInput.cs b/ShiftOS.Frontend/GUI/TextInput.cs index 73954ef..5f824a0 100644 --- a/ShiftOS.Frontend/GUI/TextInput.cs +++ b/ShiftOS.Frontend/GUI/TextInput.cs @@ -37,6 +37,16 @@ namespace ShiftOS.Frontend.GUI } } + public override void MouseStateChanged() + { + if (MouseLeftDown == true) + { + UIManager.FocusedControl = this; + Invalidate(); + } + base.MouseStateChanged(); + } + public string Text { get @@ -51,7 +61,7 @@ namespace ShiftOS.Frontend.GUI _text = value; if(_index >= _text.Length) { - _index = _text.Length - 1; + _index = _text.Length; } Invalidate(); } @@ -117,22 +127,26 @@ namespace ShiftOS.Frontend.GUI protected override void OnPaint(GraphicsContext gfx) { - gfx.Clear(LoadedSkin.ControlColor.ToMonoColor()); - gfx.DrawString(_text, 2 - (int)Math.Floor(_textDrawOffset), 2, LoadedSkin.ControlTextColor.ToMonoColor(), _font); + gfx.DrawRectangle(0, 0, Width, Height, UIManager.SkinTextures["ControlTextColor"]); + gfx.DrawRectangle(1, 1, Width - 2, Height - 2, UIManager.SkinTextures["ControlColor"]); + + if (!string.IsNullOrWhiteSpace(Text)) + { + gfx.DrawString(Text, (int)(2 - _textDrawOffset), 2, LoadedSkin.ControlTextColor.ToMonoColor(), _font); + } if (IsFocusedControl) { - //Draw caret. - - - gfx.DrawRectangle((int)(Math.Floor(caretPos) - Math.Floor(_textDrawOffset)), 2, 2, Height - 4, LoadedSkin.ControlTextColor.ToMonoColor()); + //draw caret + gfx.DrawRectangle((int)(caretPos - _textDrawOffset), 2, 2, Height - 4, UIManager.SkinTextures["ControlTextColor"]); } else { - if (string.IsNullOrEmpty(_text)) + if(string.IsNullOrWhiteSpace(Text) && !string.IsNullOrWhiteSpace(_label)) { gfx.DrawString(_label, 2, 2, Color.Gray, _font); } } + } } } diff --git a/ShiftOS.Frontend/ShiftOS.Frontend.csproj b/ShiftOS.Frontend/ShiftOS.Frontend.csproj index d50b022..c029107 100644 --- a/ShiftOS.Frontend/ShiftOS.Frontend.csproj +++ b/ShiftOS.Frontend/ShiftOS.Frontend.csproj @@ -42,6 +42,7 @@ app.manifest +