dropped the gui prefix on most of the gui stuff

This commit is contained in:
Dylan Wilson
2018-03-05 22:06:57 +10:00
parent c9a4cf37a9
commit 0c8ccf5125
41 changed files with 314 additions and 317 deletions
@@ -0,0 +1,285 @@
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using MonoGame.Extended.Input.InputListeners;
using System.Collections.Generic;
using MonoGame.Extended.BitmapFonts;
namespace MonoGame.Extended.Gui.Controls
{
public class TextBox : Control
{
public TextBox(string text = null)
{
Text = text ?? string.Empty;
}
public int SelectionStart { get; set; }
public char? PasswordCharacter { get; set; }
public Thickness Padding { get; set; }
protected override void OnTextChanged()
{
if (!string.IsNullOrEmpty(Text) && SelectionStart > Text.Length)
SelectionStart = Text.Length;
base.OnTextChanged();
}
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, BoundingRectangle, HorizontalAlignment.Centre, VerticalAlignment.Centre);
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);
_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>();
protected override void DrawForeground(IGuiContext context, IGuiRenderer renderer, float deltaSeconds, TextInfo textInfo)
{
if (PasswordCharacter.HasValue)
textInfo = GetTextInfo(context, new string(PasswordCharacter.Value, textInfo.Text.Length), BoundingRectangle, HorizontalAlignment.Centre, VerticalAlignment.Centre);
base.DrawForeground(context, renderer, deltaSeconds, textInfo);
if (IsFocused)
{
var caretRectangle = GetCaretRectangle(textInfo, SelectionStart);
if (_isCaretVisible)
renderer.DrawRectangle((Rectangle)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 RectangleF 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 caretRectangle;
}
}
}