2019-08-10 19:23:08 +02:00
|
|
|
using System;
|
2019-08-18 17:59:14 +02:00
|
|
|
using System.Linq;
|
2019-08-10 19:23:08 +02:00
|
|
|
using System.Text;
|
|
|
|
using Microsoft.Xna.Framework;
|
|
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
|
using Microsoft.Xna.Framework.Input;
|
2019-08-12 19:44:16 +02:00
|
|
|
using MLEM.Extensions;
|
2019-08-10 19:23:08 +02:00
|
|
|
using MLEM.Font;
|
|
|
|
using MLEM.Textures;
|
2019-08-10 21:37:10 +02:00
|
|
|
using MLEM.Ui.Style;
|
2019-08-10 19:23:08 +02:00
|
|
|
|
|
|
|
namespace MLEM.Ui.Elements {
|
|
|
|
public class TextField : Element {
|
|
|
|
|
2019-08-18 17:59:14 +02:00
|
|
|
public static readonly Rule DefaultRule = (field, add) => !add.Any(char.IsControl);
|
|
|
|
public static readonly Rule OnlyLetters = (field, add) => add.All(char.IsLetter);
|
|
|
|
public static readonly Rule OnlyNumbers = (field, add) => add.All(char.IsNumber);
|
|
|
|
public static readonly Rule LettersNumbers = (field, add) => add.All(c => char.IsLetter(c) || char.IsNumber(c));
|
|
|
|
|
2019-08-10 21:37:10 +02:00
|
|
|
public NinePatch Texture;
|
|
|
|
public NinePatch HoveredTexture;
|
|
|
|
public Color HoveredColor;
|
2019-08-10 19:23:08 +02:00
|
|
|
public float TextScale;
|
|
|
|
public readonly StringBuilder Text = new StringBuilder();
|
|
|
|
public TextChanged OnTextChange;
|
|
|
|
public int MaxTextLength = int.MaxValue;
|
|
|
|
public float TextOffsetX = 4;
|
2019-08-10 21:37:10 +02:00
|
|
|
private IGenericFont font;
|
2019-08-10 19:23:08 +02:00
|
|
|
private double caretBlinkTimer;
|
2019-08-11 00:39:40 +02:00
|
|
|
private int textStartIndex;
|
2019-08-18 17:59:14 +02:00
|
|
|
public Rule InputRule;
|
2019-08-10 19:23:08 +02:00
|
|
|
|
2019-08-18 17:59:14 +02:00
|
|
|
public TextField(Anchor anchor, Vector2 size, Rule rule = null, IGenericFont font = null) : base(anchor, size) {
|
|
|
|
this.InputRule = rule ?? DefaultRule;
|
2019-08-10 21:37:10 +02:00
|
|
|
this.font = font;
|
2019-08-10 19:23:08 +02:00
|
|
|
this.OnTextInput += (element, key, character) => {
|
|
|
|
if (!this.IsSelected)
|
|
|
|
return;
|
|
|
|
var textChanged = false;
|
|
|
|
if (key == Keys.Back) {
|
|
|
|
if (this.Text.Length > 0) {
|
|
|
|
this.Text.Remove(this.Text.Length - 1, 1);
|
|
|
|
textChanged = true;
|
|
|
|
}
|
2019-08-18 17:59:14 +02:00
|
|
|
} else if (this.InputRule(this, character.ToString())) {
|
2019-08-10 19:23:08 +02:00
|
|
|
if (this.Text.Length < this.MaxTextLength) {
|
|
|
|
this.Text.Append(character);
|
|
|
|
textChanged = true;
|
|
|
|
}
|
|
|
|
}
|
2019-08-11 00:39:40 +02:00
|
|
|
if (textChanged) {
|
|
|
|
var length = this.font.MeasureString(this.Text).X * this.TextScale;
|
2019-08-11 21:41:04 +02:00
|
|
|
var maxWidth = this.DisplayArea.Width / this.Scale - this.TextOffsetX * 2;
|
2019-08-11 00:39:40 +02:00
|
|
|
if (length > maxWidth) {
|
2019-08-11 14:18:07 +02:00
|
|
|
for (var i = 0; i < this.Text.Length; i++) {
|
2019-08-11 00:39:40 +02:00
|
|
|
var substring = this.Text.ToString(i, this.Text.Length - i);
|
|
|
|
if (this.font.MeasureString(substring).X * this.TextScale <= maxWidth) {
|
|
|
|
this.textStartIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.textStartIndex = 0;
|
|
|
|
}
|
|
|
|
|
2019-08-10 19:23:08 +02:00
|
|
|
this.OnTextChange?.Invoke(this, this.Text.ToString());
|
2019-08-11 00:39:40 +02:00
|
|
|
}
|
2019-08-10 19:23:08 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Update(GameTime time) {
|
|
|
|
base.Update(time);
|
|
|
|
|
|
|
|
this.caretBlinkTimer += time.ElapsedGameTime.TotalSeconds;
|
|
|
|
if (this.caretBlinkTimer >= 1)
|
|
|
|
this.caretBlinkTimer = 0;
|
|
|
|
}
|
|
|
|
|
2019-08-12 19:44:16 +02:00
|
|
|
public override void Draw(GameTime time, SpriteBatch batch, float alpha, Point offset) {
|
2019-08-10 19:23:08 +02:00
|
|
|
var tex = this.Texture;
|
|
|
|
var color = Color.White * alpha;
|
|
|
|
if (this.IsMouseOver) {
|
|
|
|
if (this.HoveredTexture != null)
|
|
|
|
tex = this.HoveredTexture;
|
|
|
|
color = this.HoveredColor * alpha;
|
|
|
|
}
|
2019-08-12 19:44:16 +02:00
|
|
|
batch.Draw(tex, this.DisplayArea.OffsetCopy(offset), color, this.Scale);
|
2019-08-10 19:23:08 +02:00
|
|
|
var caret = this.IsSelected && this.caretBlinkTimer >= 0.5F ? "|" : "";
|
2019-08-11 00:39:40 +02:00
|
|
|
var text = this.Text.ToString(this.textStartIndex, this.Text.Length - this.textStartIndex) + caret;
|
2019-08-12 19:44:16 +02:00
|
|
|
this.font.DrawCenteredString(batch, text, this.DisplayArea.Location.ToVector2() + new Vector2(offset.X + this.TextOffsetX * this.Scale, offset.Y + this.DisplayArea.Height / 2), this.TextScale * this.Scale, Color.White * alpha, false, true);
|
|
|
|
base.Draw(time, batch, alpha, offset);
|
2019-08-10 19:23:08 +02:00
|
|
|
}
|
|
|
|
|
2019-08-10 21:37:10 +02:00
|
|
|
protected override void InitStyle(UiStyle style) {
|
|
|
|
base.InitStyle(style);
|
|
|
|
this.TextScale = style.TextScale;
|
|
|
|
this.font = style.Font;
|
|
|
|
this.Texture = style.TextFieldTexture;
|
|
|
|
this.HoveredTexture = style.TextFieldHoveredTexture;
|
|
|
|
this.HoveredColor = style.TextFieldHoveredColor;
|
|
|
|
}
|
|
|
|
|
2019-08-10 19:23:08 +02:00
|
|
|
public delegate void TextChanged(TextField field, string text);
|
|
|
|
|
2019-08-18 17:59:14 +02:00
|
|
|
public delegate bool Rule(TextField field, string textToAdd);
|
|
|
|
|
2019-08-10 19:23:08 +02:00
|
|
|
}
|
|
|
|
}
|