summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2024-06-03 10:15:45 +0800
committerchai <215380520@qq.com>2024-06-03 10:15:45 +0800
commitacea7b2e728787a0d83bbf83c8c1f042d2c32e7e (patch)
tree0bfec05c1ca2d71be2c337bcd110a0421f19318b /Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs
parent88febcb02bf127d961c6471d9e846c0e1315f5c3 (diff)
+ plugins project
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs')
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs328
1 files changed, 328 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs
new file mode 100644
index 0000000..e20b621
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox2.cs
@@ -0,0 +1,328 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+using MonoGame.Extended.Input.InputListeners;
+
+namespace MonoGame.Extended.Gui.Controls
+{
+ public class TextBox2 : Control
+ {
+ public TextBox2()
+ : this(null)
+ {
+ }
+
+ public TextBox2(string text)
+ {
+ Text = text ?? string.Empty;
+ HorizontalTextAlignment = HorizontalAlignment.Left;
+ VerticalTextAlignment = VerticalAlignment.Top;
+ }
+
+
+ private const float _caretBlinkRate = 0.53f;
+ private float _nextCaretBlink = _caretBlinkRate;
+ private bool _isCaretVisible = true;
+
+ private readonly List<StringBuilder> _lines = new List<StringBuilder>();
+ public string Text
+ {
+ get => string.Concat(_lines.SelectMany(s => $"{s}\n"));
+ set
+ {
+ _lines.Clear();
+
+ var line = new StringBuilder();
+
+ for (var i = 0; i < value.Length; i++)
+ {
+ var c = value[i];
+
+ if (c == '\n')
+ {
+ _lines.Add(line);
+ line = new StringBuilder();
+ }
+ else if(c != '\r')
+ {
+ line.Append(c);
+ }
+ }
+
+ _lines.Add(line);
+ }
+ }
+
+ public int CaretIndex => ColumnIndex * LineIndex + ColumnIndex;
+ public int LineIndex { get; set; }
+ public int ColumnIndex { get; set; }
+ public int TabStops { get; set; } = 4;
+
+ public override IEnumerable<Control> Children => Enumerable.Empty<Control>();
+
+ public string GetLineText(int lineIndex) => _lines[lineIndex].ToString();
+ public int GetLineLength(int lineIndex) => _lines[lineIndex].Length;
+
+ public override Size GetContentSize(IGuiContext context)
+ {
+ var font = Font ?? context.DefaultFont;
+ var stringSize = (Size)font.MeasureString(Text ?? string.Empty);
+ return new Size(stringSize.Width, stringSize.Height < font.LineHeight ? font.LineHeight : stringSize.Height);
+ }
+
+ public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
+ {
+ switch (args.Key)
+ {
+ case Keys.Tab:
+ Tab();
+ break;
+ case Keys.Back:
+ Backspace();
+ break;
+ case Keys.Delete:
+ Delete();
+ break;
+ case Keys.Left:
+ Left();
+ break;
+ case Keys.Right:
+ Right();
+ break;
+ case Keys.Up:
+ Up();
+ break;
+ case Keys.Down:
+ Down();
+ break;
+ case Keys.Home:
+ Home();
+ break;
+ case Keys.End:
+ End();
+ break;
+ case Keys.Enter:
+ Type('\n');
+ return true;
+ default:
+ if (args.Character.HasValue)
+ Type(args.Character.Value);
+
+ break;
+ }
+
+ _isCaretVisible = true;
+ return base.OnKeyPressed(context, args);
+ }
+
+ public void Type(char c)
+ {
+ switch (c)
+ {
+ case '\n':
+ var lineText = GetLineText(LineIndex);
+ var left = lineText.Substring(0, ColumnIndex);
+ var right = lineText.Substring(ColumnIndex);
+ _lines.Insert(LineIndex + 1, new StringBuilder(right));
+ _lines[LineIndex] = new StringBuilder(left);
+ LineIndex++;
+ Home();
+ break;
+ case '\t':
+ Tab();
+ break;
+ default:
+ _lines[LineIndex].Insert(ColumnIndex, c);
+ ColumnIndex++;
+ break;
+ }
+ }
+
+ public void Backspace()
+ {
+ if (ColumnIndex == 0 && LineIndex > 0)
+ {
+ var topLineLength = GetLineLength(LineIndex - 1);
+
+ if (RemoveLineBreak(LineIndex - 1))
+ {
+ LineIndex--;
+ ColumnIndex = topLineLength;
+ }
+ }
+ else if (Left())
+ {
+ RemoveCharacter(LineIndex, ColumnIndex);
+ }
+ }
+
+ public void Delete()
+ {
+ var lineLength = GetLineLength(LineIndex);
+
+ if (ColumnIndex == lineLength)
+ RemoveLineBreak(LineIndex);
+ else
+ RemoveCharacter(LineIndex, ColumnIndex);
+ }
+
+ public void RemoveCharacter(int lineIndex, int columnIndex)
+ {
+ _lines[lineIndex].Remove(columnIndex, 1);
+ }
+
+ public bool RemoveLineBreak(int lineIndex)
+ {
+ if (lineIndex < _lines.Count - 1)
+ {
+ var topLine = _lines[lineIndex];
+ var bottomLine = _lines[lineIndex + 1];
+ _lines.RemoveAt(lineIndex + 1);
+ topLine.Append(bottomLine);
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool Home()
+ {
+ ColumnIndex = 0;
+ return true;
+ }
+
+ public bool End()
+ {
+ ColumnIndex = GetLineLength(LineIndex);
+ return true;
+ }
+
+ public bool Up()
+ {
+ if (LineIndex > 0)
+ {
+ LineIndex--;
+
+ if (ColumnIndex > GetLineLength(LineIndex))
+ ColumnIndex = GetLineLength(LineIndex);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool Down()
+ {
+ if (LineIndex < _lines.Count - 1)
+ {
+ LineIndex++;
+
+ if (ColumnIndex > GetLineLength(LineIndex))
+ ColumnIndex = GetLineLength(LineIndex);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool Left()
+ {
+ if (ColumnIndex == 0)
+ {
+ if (LineIndex == 0)
+ return false;
+
+ LineIndex--;
+ ColumnIndex = GetLineLength(LineIndex);
+ }
+ else
+ {
+ ColumnIndex--;
+ }
+
+ return true;
+ }
+
+ public bool Right()
+ {
+ if (ColumnIndex == _lines[LineIndex].Length)
+ {
+ if (LineIndex == _lines.Count - 1)
+ return false;
+
+ LineIndex++;
+ ColumnIndex = 0;
+ }
+ else
+ {
+ ColumnIndex++;
+ }
+
+ return true;
+ }
+
+ public bool Tab()
+ {
+ var spaces = TabStops - ColumnIndex % TabStops;
+
+ for (var s = 0; s < spaces; s++)
+ Type(' ');
+
+ return spaces > 0;
+ }
+
+ public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds)
+ {
+ base.Draw(context, renderer, deltaSeconds);
+
+ var text = Text;
+ var textInfo = GetTextInfo(context, text, ContentRectangle, HorizontalTextAlignment, VerticalTextAlignment);
+
+ if (!string.IsNullOrWhiteSpace(textInfo.Text))
+ renderer.DrawText(textInfo.Font, textInfo.Text, textInfo.Position + TextOffset, textInfo.Color, textInfo.ClippingRectangle);
+
+ if (IsFocused)
+ {
+ var caretRectangle = GetCaretRectangle(textInfo);
+
+ if (_isCaretVisible)
+ renderer.DrawRectangle(caretRectangle, TextColor);
+
+ _nextCaretBlink -= deltaSeconds;
+
+ if (_nextCaretBlink <= 0)
+ {
+ _isCaretVisible = !_isCaretVisible;
+ _nextCaretBlink = _caretBlinkRate;
+ }
+ }
+ }
+
+ private Rectangle GetCaretRectangle(TextInfo textInfo)
+ {
+ var font = textInfo.Font;
+ var text = GetLineText(LineIndex);
+ var offset = new Vector2(0, font.LineHeight * LineIndex);
+ var caretRectangle = font.GetStringRectangle(text.Substring(0, ColumnIndex), textInfo.Position + offset);
+
+ // TODO: Finish the caret position stuff when it's outside the clipping rectangle
+ if (caretRectangle.Right > ClippingRectangle.Right)
+ textInfo.Position.X -= caretRectangle.Right - ClippingRectangle.Right;
+
+ caretRectangle.X = caretRectangle.Right < ClippingRectangle.Right ? caretRectangle.Right : ClippingRectangle.Right;
+ caretRectangle.Width = 1;
+
+ if (caretRectangle.Left < ClippingRectangle.Left)
+ {
+ textInfo.Position.X += ClippingRectangle.Left - caretRectangle.Left;
+ caretRectangle.X = ClippingRectangle.Left;
+ }
+
+ return (Rectangle)caretRectangle;
+ }
+ }
+} \ No newline at end of file