diff options
author | chai <215380520@qq.com> | 2024-06-03 10:15:45 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-06-03 10:15:45 +0800 |
commit | acea7b2e728787a0d83bbf83c8c1f042d2c32e7e (patch) | |
tree | 0bfec05c1ca2d71be2c337bcd110a0421f19318b /Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox.cs | |
parent | 88febcb02bf127d961c6471d9e846c0e1315f5c3 (diff) |
+ plugins project
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox.cs')
-rw-r--r-- | Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox.cs | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox.cs new file mode 100644 index 0000000..75b6940 --- /dev/null +++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Gui/Controls/TextBox.cs @@ -0,0 +1,331 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using MonoGame.Extended.Input.InputListeners; + +namespace MonoGame.Extended.Gui.Controls +{ + public sealed class TextBox : Control + { + public TextBox(string text = null) + { + Text = text ?? string.Empty; + HorizontalTextAlignment = HorizontalAlignment.Left; + } + + public TextBox() + : this(null) + { + } + + public int SelectionStart { get; set; } + public char? PasswordCharacter { get; set; } + + private string _text; + + public string Text + { + get { return _text; } + set + { + if (_text != value) + { + _text = value; + OnTextChanged(); + } + } + } + + private void OnTextChanged() + { + if (!string.IsNullOrEmpty(Text) && SelectionStart > Text.Length) + SelectionStart = Text.Length; + + TextChanged?.Invoke(this, EventArgs.Empty); + } + + public event EventHandler TextChanged; + + public override IEnumerable<Control> Children { get; } = Enumerable.Empty<Control>(); + + 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); + } + + //protected override Size2 CalculateDesiredSize(IGuiContext context, Size2 availableSize) + //{ + // var font = Font ?? context.DefaultFont; + // return new Size2(Width + Padding.Left + Padding.Right, (Height <= 0.0f ? font.LineHeight + 2 : Height) + Padding.Top + Padding.Bottom); + //} + + public override bool OnPointerDown(IGuiContext context, PointerEventArgs args) + { + SelectionStart = FindNearestGlyphIndex(context, args.Position); + _isCaretVisible = true; + + //_selectionIndexes.Clear(); + //_selectionIndexes.Push(SelectionStart); + //_startSelectionBox = Text.Length > 0; + + return base.OnPointerDown(context, args); + } + + //public override bool OnPointerMove(IGuiContext context, PointerEventArgs args) + //{ + // if (_startSelectionBox) + // { + // var selection = FindNearestGlyphIndex(context, args.Position); + // if (selection != _selectionIndexes.Peek()) + // { + // if (_selectionIndexes.Count == 1) + // { + // _selectionIndexes.Push(selection); + // } + // else if (_selectionIndexes.Last() < _selectionIndexes.Peek()) + // { + // if (selection > _selectionIndexes.Peek()) _selectionIndexes.Pop(); + // else _selectionIndexes.Push(selection); + // } + // else + // { + // if (selection < _selectionIndexes.Peek()) _selectionIndexes.Pop(); + // else _selectionIndexes.Push(selection); + // } + // SelectionStart = selection; + // } + // } + + // return base.OnPointerMove(context, args); + //} + + //public override bool OnPointerLeave(IGuiContext context, PointerEventArgs args) + //{ + // _startSelectionBox = false; + + // return base.OnPointerLeave(context, args); + //} + + //public override bool OnPointerUp(IGuiContext context, PointerEventArgs args) + //{ + // _startSelectionBox = false; + + // return base.OnPointerUp(context, args); + //} + + private int FindNearestGlyphIndex(IGuiContext context, Point position) + { + var font = Font ?? context.DefaultFont; + var textInfo = GetTextInfo(context, Text, ContentRectangle, HorizontalTextAlignment, VerticalTextAlignment); + var i = 0; + + foreach (var glyph in font.GetGlyphs(textInfo.Text, textInfo.Position)) + { + var fontRegionWidth = glyph.FontRegion?.Width ?? 0; + var glyphMiddle = (int) (glyph.Position.X + fontRegionWidth * 0.5f); + + if (position.X >= glyphMiddle) + { + i++; + continue; + } + + return i; + } + + return i; + } + + public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args) + { + switch (args.Key) + { + case Keys.Tab: + case Keys.Enter: + return true; + case Keys.Back: + if (Text.Length > 0) + { + if (SelectionStart > 0) // && _selectionIndexes.Count <= 1) + { + SelectionStart--; + Text = Text.Remove(SelectionStart, 1); + } + //else + //{ + // var start = MathHelper.Min(_selectionIndexes.Last(), _selectionIndexes.Peek()); + // var end = MathHelper.Max(_selectionIndexes.Last(), _selectionIndexes.Peek()); + // Text = Text.Remove(start, end - start); + + // _selectionIndexes.Clear(); + //} + } + + break; + case Keys.Delete: + if (SelectionStart < Text.Length) // && _selectionIndexes.Count <= 1) + { + Text = Text.Remove(SelectionStart, 1); + } + //else if (_selectionIndexes.Count > 1) + //{ + // var start = MathHelper.Min(_selectionIndexes.Last(), _selectionIndexes.Peek()); + // var end = MathHelper.Max(_selectionIndexes.Last(), _selectionIndexes.Peek()); + // Text = Text.Remove(start, end - start); + // SelectionStart = 0; // yeah, nah. + + // _selectionIndexes.Clear(); + //} + break; + case Keys.Left: + if (SelectionStart > 0) + { + //if (_selectionIndexes.Count > 1) + //{ + // if (_selectionIndexes.Last() < SelectionStart) SelectionStart = _selectionIndexes.Last(); + // _selectionIndexes.Clear(); + //} + //else + { + SelectionStart--; + } + } + + break; + case Keys.Right: + if (SelectionStart < Text.Length) + { + //if (_selectionIndexes.Count > 1) + //{ + // if (_selectionIndexes.Last() > SelectionStart) SelectionStart = _selectionIndexes.Last(); + // _selectionIndexes.Clear(); + //} + //else + { + SelectionStart++; + } + } + + break; + case Keys.Home: + SelectionStart = 0; + //_selectionIndexes.Clear(); + break; + case Keys.End: + SelectionStart = Text.Length; + //_selectionIndexes.Clear(); + break; + default: + if (args.Character != null) + { + //if (_selectionIndexes.Count > 1) + //{ + // var start = MathHelper.Min(_selectionIndexes.Last(), _selectionIndexes.Peek()); + // var end = MathHelper.Max(_selectionIndexes.Last(), _selectionIndexes.Peek()); + // Text = Text.Remove(start, end - start); + + // _selectionIndexes.Clear(); + //} + + Text = Text.Insert(SelectionStart, args.Character.ToString()); + SelectionStart++; + } + + break; + } + + _isCaretVisible = true; + return base.OnKeyPressed(context, args); + } + + private const float _caretBlinkRate = 0.53f; + private float _nextCaretBlink = _caretBlinkRate; + private bool _isCaretVisible = true; + + //private bool _startSelectionBox = false; + //private Stack<int> _selectionIndexes = new Stack<int>(); + + public override void Draw(IGuiContext context, IGuiRenderer renderer, float deltaSeconds) + { + base.Draw(context, renderer, deltaSeconds); + + var text = PasswordCharacter.HasValue ? new string(PasswordCharacter.Value, Text.Length) : 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, SelectionStart); + + if (_isCaretVisible) + renderer.DrawRectangle(caretRectangle, TextColor); + + _nextCaretBlink -= deltaSeconds; + + if (_nextCaretBlink <= 0) + { + _isCaretVisible = !_isCaretVisible; + _nextCaretBlink = _caretBlinkRate; + } + + //if (_selectionIndexes.Count > 1) + //{ + // var start = 0; + // var end = 0; + // var point = Point2.Zero; + // if (_selectionIndexes.Last() > _selectionIndexes.Peek()) + // { + // start = _selectionIndexes.Peek(); + // end = _selectionIndexes.Last(); + // point = caretRectangle.Position; + // } + // else + // { + // start = _selectionIndexes.Last(); + // end = _selectionIndexes.Peek(); + // point = GetCaretRectangle(textInfo, start).Position; + // } + // var selectionRectangle = textInfo.Font.GetStringRectangle(textInfo.Text.Substring(start, end - start), point); + + // renderer.FillRectangle((Rectangle)selectionRectangle, Color.Black * 0.25f); + //} + } + } + + + //protected override string CreateBoxText(string text, BitmapFont font, float width) + //{ + // return text; + //} + + private Rectangle GetCaretRectangle(TextInfo textInfo, int index) + { + var caretRectangle = textInfo.Font.GetStringRectangle(textInfo.Text.Substring(0, index), textInfo.Position); + + // 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 |