mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-24 21:48:35 +01:00
Compare commits
2 commits
9aef994c51
...
5f2eb1845f
Author | SHA1 | Date | |
---|---|---|---|
5f2eb1845f | |||
a47318c0a2 |
2 changed files with 194 additions and 167 deletions
|
@ -22,6 +22,7 @@ Improvements
|
||||||
|
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed VerticalSpace height parameter being an integer
|
- Fixed VerticalSpace height parameter being an integer
|
||||||
|
- Fixed text not being pasted into a text field at all if it contains characters that don't match the input rule
|
||||||
|
|
||||||
## 5.1.0
|
## 5.1.0
|
||||||
### MLEM
|
### MLEM
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
@ -146,6 +147,16 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The line of text that the caret is currently on.
|
||||||
|
/// This can only be only non-0 if <see cref="Multiline"/> is true.
|
||||||
|
/// </summary>
|
||||||
|
public int CaretLine { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The position in the current <see cref="CaretLine"/> that the caret is currently on.
|
||||||
|
/// If <see cref="Multiline"/> is false, this value is always equal to <see cref="CaretPos"/>.
|
||||||
|
/// </summary>
|
||||||
|
public int CaretPosInLine { get; private set; }
|
||||||
|
/// <summary>
|
||||||
/// A character that should be displayed instead of this text field's <see cref="Text"/> content.
|
/// A character that should be displayed instead of this text field's <see cref="Text"/> content.
|
||||||
/// The amount of masking characters displayed will be equal to the <see cref="Text"/>'s length.
|
/// The amount of masking characters displayed will be equal to the <see cref="Text"/>'s length.
|
||||||
/// This behavior is useful for password fields or similar.
|
/// This behavior is useful for password fields or similar.
|
||||||
|
@ -167,6 +178,9 @@ namespace MLEM.Ui.Elements {
|
||||||
/// If this is true, pressing <see cref="Keys.Enter"/> will insert a new line into the <see cref="Text"/> if the <see cref="InputRule"/> allows it.
|
/// If this is true, pressing <see cref="Keys.Enter"/> will insert a new line into the <see cref="Text"/> if the <see cref="InputRule"/> allows it.
|
||||||
/// Additionally, text will be rendered with horizontal soft wraps, and lines that are outside of the text field's bounds will be hidden.
|
/// Additionally, text will be rendered with horizontal soft wraps, and lines that are outside of the text field's bounds will be hidden.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Moving up and down through the text field, and clicking on text to start editing at the mouse's position, are currently not supported.
|
||||||
|
/// </remarks>
|
||||||
public bool Multiline {
|
public bool Multiline {
|
||||||
get => this.multiline;
|
get => this.multiline;
|
||||||
set {
|
set {
|
||||||
|
@ -180,9 +194,11 @@ namespace MLEM.Ui.Elements {
|
||||||
private char? maskingCharacter;
|
private char? maskingCharacter;
|
||||||
private double caretBlinkTimer;
|
private double caretBlinkTimer;
|
||||||
private string displayedText;
|
private string displayedText;
|
||||||
|
private string[] splitText;
|
||||||
private int textOffset;
|
private int textOffset;
|
||||||
private int lineOffset;
|
private int lineOffset;
|
||||||
private int caretPos;
|
private int caretPos;
|
||||||
|
private float caretDrawOffset;
|
||||||
private bool multiline;
|
private bool multiline;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -232,6 +248,146 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Update(GameTime time) {
|
||||||
|
base.Update(time);
|
||||||
|
|
||||||
|
// handle first initialization if not done
|
||||||
|
if (this.displayedText == null)
|
||||||
|
this.HandleTextChange(false);
|
||||||
|
|
||||||
|
if (!this.IsSelected || this.IsHidden)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.Input.IsKeyPressed(Keys.Left)) {
|
||||||
|
this.CaretPos--;
|
||||||
|
} else if (this.Input.IsKeyPressed(Keys.Right)) {
|
||||||
|
this.CaretPos++;
|
||||||
|
} else if (this.Input.IsKeyPressed(Keys.Home)) {
|
||||||
|
this.CaretPos = 0;
|
||||||
|
} else if (this.Input.IsKeyPressed(Keys.End)) {
|
||||||
|
this.CaretPos = this.text.Length;
|
||||||
|
} else if (this.Input.IsModifierKeyDown(ModifierKey.Control)) {
|
||||||
|
if (this.Input.IsKeyPressed(Keys.V)) {
|
||||||
|
var clip = ClipboardService.GetText();
|
||||||
|
if (clip != null)
|
||||||
|
this.InsertText(clip, true);
|
||||||
|
} else if (this.Input.IsKeyPressed(Keys.C)) {
|
||||||
|
// until there is text selection, just copy the whole content
|
||||||
|
ClipboardService.SetText(this.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.caretBlinkTimer += time.ElapsedGameTime.TotalSeconds;
|
||||||
|
if (this.caretBlinkTimer >= 1)
|
||||||
|
this.caretBlinkTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
||||||
|
var tex = this.Texture;
|
||||||
|
var color = Color.White * alpha;
|
||||||
|
if (this.IsMouseOver) {
|
||||||
|
tex = this.HoveredTexture.OrDefault(tex);
|
||||||
|
color = (Color) this.HoveredColor * alpha;
|
||||||
|
}
|
||||||
|
batch.Draw(tex, this.DisplayArea, color, this.Scale);
|
||||||
|
|
||||||
|
if (this.displayedText != null) {
|
||||||
|
var lineHeight = this.Font.Value.LineHeight * this.TextScale * this.Scale;
|
||||||
|
var offset = new Vector2(
|
||||||
|
this.TextOffsetX * this.Scale,
|
||||||
|
this.Multiline ? this.TextOffsetX * this.Scale : this.DisplayArea.Height / 2 - lineHeight / 2);
|
||||||
|
var textPos = this.DisplayArea.Location + offset;
|
||||||
|
if (this.text.Length > 0 || this.IsSelected) {
|
||||||
|
var textColor = this.TextColor.OrDefault(Color.White);
|
||||||
|
this.Font.Value.DrawString(batch, this.displayedText, textPos, textColor * alpha, 0, Vector2.Zero, this.TextScale * this.Scale, SpriteEffects.None, 0);
|
||||||
|
|
||||||
|
if (this.IsSelected && this.caretBlinkTimer < 0.5F) {
|
||||||
|
var caretDrawPos = textPos + new Vector2(this.caretDrawOffset * this.TextScale * this.Scale, 0);
|
||||||
|
if (this.Multiline)
|
||||||
|
caretDrawPos.Y += this.Font.Value.LineHeight * (this.CaretLine - this.lineOffset) * this.TextScale * this.Scale;
|
||||||
|
batch.Draw(batch.GetBlankTexture(), new RectangleF(caretDrawPos, new Vector2(this.CaretWidth * this.Scale, lineHeight)), null, textColor * alpha);
|
||||||
|
}
|
||||||
|
} else if (this.PlaceholderText != null) {
|
||||||
|
this.Font.Value.DrawString(batch, this.PlaceholderText, textPos, this.PlaceholderColor.OrDefault(Color.Gray) * alpha, 0, Vector2.Zero, this.TextScale * this.Scale, SpriteEffects.None, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Draw(time, batch, alpha, blendState, samplerState, matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces this text field's text with the given text.
|
||||||
|
/// If the resulting <see cref="Text"/> exceeds <see cref="MaximumCharacters"/>, the end will be cropped to fit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The new text</param>
|
||||||
|
/// <param name="removeMismatching">If any characters that don't match the <see cref="InputRule"/> should be left out</param>
|
||||||
|
public void SetText(object text, bool removeMismatching = false) {
|
||||||
|
var strg = text?.ToString() ?? string.Empty;
|
||||||
|
if (!this.FilterText(ref strg, removeMismatching))
|
||||||
|
return;
|
||||||
|
if (this.MaximumCharacters != null && strg.Length > this.MaximumCharacters)
|
||||||
|
strg = strg.Substring(0, this.MaximumCharacters.Value);
|
||||||
|
this.text.Clear();
|
||||||
|
this.text.Append(strg);
|
||||||
|
this.CaretPos = this.text.Length;
|
||||||
|
this.HandleTextChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts the given text at the <see cref="CaretPos"/>.
|
||||||
|
/// If the resulting <see cref="Text"/> exceeds <see cref="MaximumCharacters"/>, the end will be cropped to fit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text to insert</param>
|
||||||
|
/// <param name="removeMismatching">If any characters that don't match the <see cref="InputRule"/> should be left out</param>
|
||||||
|
public void InsertText(object text, bool removeMismatching = false) {
|
||||||
|
var strg = text?.ToString() ?? string.Empty;
|
||||||
|
if (!this.FilterText(ref strg, removeMismatching))
|
||||||
|
return;
|
||||||
|
if (this.MaximumCharacters != null && this.text.Length + strg.Length > this.MaximumCharacters)
|
||||||
|
strg = strg.Substring(0, this.MaximumCharacters.Value - this.text.Length);
|
||||||
|
this.text.Insert(this.CaretPos, strg);
|
||||||
|
this.CaretPos += strg.Length;
|
||||||
|
this.HandleTextChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the given amount of text at the given index
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">The index</param>
|
||||||
|
/// <param name="length">The amount of text to remove</param>
|
||||||
|
public void RemoveText(int index, int length) {
|
||||||
|
if (index < 0 || index >= this.text.Length)
|
||||||
|
return;
|
||||||
|
this.text.Remove(index, length);
|
||||||
|
// ensure that caret pos is still in bounds
|
||||||
|
this.CaretPos = this.CaretPos;
|
||||||
|
this.HandleTextChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void InitStyle(UiStyle style) {
|
||||||
|
base.InitStyle(style);
|
||||||
|
this.TextScale.SetFromStyle(style.TextScale);
|
||||||
|
this.Font.SetFromStyle(style.Font);
|
||||||
|
this.Texture.SetFromStyle(style.TextFieldTexture);
|
||||||
|
this.HoveredTexture.SetFromStyle(style.TextFieldHoveredTexture);
|
||||||
|
this.HoveredColor.SetFromStyle(style.TextFieldHoveredColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool FilterText(ref string text, bool removeMismatching) {
|
||||||
|
if (removeMismatching) {
|
||||||
|
var result = new StringBuilder();
|
||||||
|
foreach (var c in text) {
|
||||||
|
if (this.InputRule(this, c.ToCachedString()))
|
||||||
|
result.Append(c);
|
||||||
|
}
|
||||||
|
text = result.ToString();
|
||||||
|
} else if (!this.InputRule(this, text))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleTextChange(bool textChanged = true) {
|
private void HandleTextChange(bool textChanged = true) {
|
||||||
// not initialized yet
|
// not initialized yet
|
||||||
if (!this.Font.HasValue())
|
if (!this.Font.HasValue())
|
||||||
|
@ -239,38 +395,26 @@ namespace MLEM.Ui.Elements {
|
||||||
var maxWidth = this.DisplayArea.Width / this.Scale - this.TextOffsetX * 2;
|
var maxWidth = this.DisplayArea.Width / this.Scale - this.TextOffsetX * 2;
|
||||||
if (this.Multiline) {
|
if (this.Multiline) {
|
||||||
// soft wrap if we're multiline
|
// soft wrap if we're multiline
|
||||||
this.displayedText = this.Font.Value.SplitString(this.text.ToString(), maxWidth, this.TextScale);
|
this.splitText = this.Font.Value.SplitStringSeparate(this.text.ToString(), maxWidth, this.TextScale).ToArray();
|
||||||
|
this.displayedText = string.Join("\n", this.splitText);
|
||||||
|
this.UpdateCaretData();
|
||||||
|
|
||||||
var maxHeight = this.DisplayArea.Height / this.Scale - this.TextOffsetX * 2;
|
var maxHeight = this.DisplayArea.Height / this.Scale - this.TextOffsetX * 2;
|
||||||
if (this.Font.Value.MeasureString(this.displayedText).Y * this.TextScale > maxHeight) {
|
if (this.Font.Value.MeasureString(this.displayedText).Y * this.TextScale > maxHeight) {
|
||||||
var maxLines = (maxHeight / (this.Font.Value.LineHeight * this.TextScale)).Floor();
|
var maxLines = (maxHeight / (this.Font.Value.LineHeight * this.TextScale)).Floor();
|
||||||
// calculate what line the caret is on
|
if (this.lineOffset > this.CaretLine) {
|
||||||
var caretLine = 0;
|
|
||||||
var originalIndex = 0;
|
|
||||||
var addedLineBreaks = 0;
|
|
||||||
for (var i = 0; i <= this.CaretPos + addedLineBreaks - 1 && i < this.displayedText.Length; i++) {
|
|
||||||
if (this.displayedText[i] == '\n') {
|
|
||||||
caretLine++;
|
|
||||||
if (this.text[originalIndex] != '\n') {
|
|
||||||
addedLineBreaks++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
originalIndex++;
|
|
||||||
}
|
|
||||||
// when we're multiline, the text offset is measured in lines
|
|
||||||
if (this.lineOffset > caretLine) {
|
|
||||||
// if we're moving up
|
// if we're moving up
|
||||||
this.lineOffset = caretLine;
|
this.lineOffset = this.CaretLine;
|
||||||
} else if (caretLine >= maxLines) {
|
} else if (this.CaretLine >= maxLines) {
|
||||||
// if we're moving down
|
// if we're moving down
|
||||||
var limit = caretLine - (maxLines - 1);
|
var limit = this.CaretLine - (maxLines - 1);
|
||||||
if (limit > this.lineOffset)
|
if (limit > this.lineOffset)
|
||||||
this.lineOffset = limit;
|
this.lineOffset = limit;
|
||||||
}
|
}
|
||||||
// calculate resulting string
|
// calculate resulting string
|
||||||
var ret = new StringBuilder();
|
var ret = new StringBuilder();
|
||||||
var lines = 0;
|
var lines = 0;
|
||||||
originalIndex = 0;
|
var originalIndex = 0;
|
||||||
for (var i = 0; i < this.displayedText.Length; i++) {
|
for (var i = 0; i < this.displayedText.Length; i++) {
|
||||||
if (lines >= this.lineOffset) {
|
if (lines >= this.lineOffset) {
|
||||||
if (ret.Length <= 0)
|
if (ret.Length <= 0)
|
||||||
|
@ -311,6 +455,7 @@ namespace MLEM.Ui.Elements {
|
||||||
this.displayedText = this.Text;
|
this.displayedText = this.Text;
|
||||||
this.textOffset = 0;
|
this.textOffset = 0;
|
||||||
}
|
}
|
||||||
|
this.UpdateCaretData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.MaskingCharacter != null)
|
if (this.MaskingCharacter != null)
|
||||||
|
@ -320,156 +465,37 @@ namespace MLEM.Ui.Elements {
|
||||||
this.OnTextChange?.Invoke(this, this.Text);
|
this.OnTextChange?.Invoke(this, this.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
private void UpdateCaretData() {
|
||||||
public override void Update(GameTime time) {
|
if (this.splitText != null) {
|
||||||
base.Update(time);
|
var line = 0;
|
||||||
|
var index = 0;
|
||||||
// handle first initialization if not done
|
for (var d = 0; d < this.splitText.Length; d++) {
|
||||||
if (this.displayedText == null)
|
var startOfLine = 0;
|
||||||
this.HandleTextChange(false);
|
var split = this.splitText[d];
|
||||||
|
for (var i = 0; i <= split.Length; i++) {
|
||||||
if (!this.IsSelected || this.IsHidden)
|
if (index == this.CaretPos) {
|
||||||
|
this.CaretLine = line;
|
||||||
|
this.CaretPosInLine = i - startOfLine;
|
||||||
|
this.caretDrawOffset = this.Font.Value.MeasureString(split.Substring(startOfLine, this.CaretPosInLine)).X;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (this.Input.IsKeyPressed(Keys.Left)) {
|
if (i < split.Length) {
|
||||||
this.CaretPos--;
|
// manual splits
|
||||||
} else if (this.Input.IsKeyPressed(Keys.Right)) {
|
if (split[i] == '\n') {
|
||||||
this.CaretPos++;
|
startOfLine = i + 1;
|
||||||
} else if (this.Input.IsKeyPressed(Keys.Home)) {
|
line++;
|
||||||
this.CaretPos = 0;
|
}
|
||||||
} else if (this.Input.IsKeyPressed(Keys.End)) {
|
index++;
|
||||||
this.CaretPos = this.text.Length;
|
|
||||||
} else if (this.Input.IsModifierKeyDown(ModifierKey.Control)) {
|
|
||||||
if (this.Input.IsKeyPressed(Keys.V)) {
|
|
||||||
var clip = ClipboardService.GetText();
|
|
||||||
if (clip != null)
|
|
||||||
this.InsertText(clip);
|
|
||||||
} else if (this.Input.IsKeyPressed(Keys.C)) {
|
|
||||||
// until there is text selection, just copy the whole content
|
|
||||||
ClipboardService.SetText(this.Text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// max width splits
|
||||||
this.caretBlinkTimer += time.ElapsedGameTime.TotalSeconds;
|
line++;
|
||||||
if (this.caretBlinkTimer >= 1)
|
|
||||||
this.caretBlinkTimer = 0;
|
|
||||||
}
|
}
|
||||||
|
} else if (this.displayedText != null) {
|
||||||
/// <inheritdoc />
|
this.CaretLine = 0;
|
||||||
public override void Draw(GameTime time, SpriteBatch batch, float alpha, BlendState blendState, SamplerState samplerState, Matrix matrix) {
|
this.CaretPosInLine = this.CaretPos;
|
||||||
var tex = this.Texture;
|
this.caretDrawOffset = this.Font.Value.MeasureString(this.displayedText.Substring(0, this.CaretPos - this.textOffset)).X;
|
||||||
var color = Color.White * alpha;
|
|
||||||
if (this.IsMouseOver) {
|
|
||||||
tex = this.HoveredTexture.OrDefault(tex);
|
|
||||||
color = (Color) this.HoveredColor * alpha;
|
|
||||||
}
|
}
|
||||||
batch.Draw(tex, this.DisplayArea, color, this.Scale);
|
|
||||||
|
|
||||||
if (this.displayedText != null) {
|
|
||||||
var lineHeight = this.Font.Value.LineHeight * this.TextScale * this.Scale;
|
|
||||||
var offset = new Vector2(
|
|
||||||
this.TextOffsetX * this.Scale,
|
|
||||||
this.Multiline ? this.TextOffsetX * this.Scale : this.DisplayArea.Height / 2 - lineHeight / 2);
|
|
||||||
var textPos = this.DisplayArea.Location + offset;
|
|
||||||
if (this.text.Length > 0 || this.IsSelected) {
|
|
||||||
var textColor = this.TextColor.OrDefault(Color.White);
|
|
||||||
this.Font.Value.DrawString(batch, this.displayedText, textPos, textColor * alpha, 0, Vector2.Zero, this.TextScale * this.Scale, SpriteEffects.None, 0);
|
|
||||||
|
|
||||||
if (this.IsSelected && this.caretBlinkTimer < 0.5F) {
|
|
||||||
var caretDrawPos = textPos;
|
|
||||||
if (this.Multiline) {
|
|
||||||
var lines = 0;
|
|
||||||
var lastLineBreak = 0;
|
|
||||||
var originalIndex = 0;
|
|
||||||
var addedLineBreaks = 0;
|
|
||||||
for (var i = 0; i <= this.CaretPos - this.textOffset + addedLineBreaks - 1 && i < this.displayedText.Length; i++) {
|
|
||||||
if (this.displayedText[i] == '\n') {
|
|
||||||
lines++;
|
|
||||||
lastLineBreak = i;
|
|
||||||
if (this.text[originalIndex] != '\n') {
|
|
||||||
addedLineBreaks++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
originalIndex++;
|
|
||||||
}
|
|
||||||
var sub = this.displayedText.Substring(lastLineBreak, this.CaretPos - this.textOffset + addedLineBreaks - lastLineBreak);
|
|
||||||
caretDrawPos += new Vector2(this.Font.Value.MeasureString(sub).X * this.TextScale * this.Scale, lineHeight * lines);
|
|
||||||
} else {
|
|
||||||
caretDrawPos.X += this.Font.Value.MeasureString(this.displayedText.Substring(0, this.CaretPos - this.textOffset)).X * this.TextScale * this.Scale;
|
|
||||||
}
|
|
||||||
batch.Draw(batch.GetBlankTexture(), new RectangleF(caretDrawPos, new Vector2(this.CaretWidth * this.Scale, lineHeight)), null, textColor * alpha);
|
|
||||||
}
|
|
||||||
} else if (this.PlaceholderText != null) {
|
|
||||||
this.Font.Value.DrawString(batch, this.PlaceholderText, textPos, this.PlaceholderColor.OrDefault(Color.Gray) * alpha, 0, Vector2.Zero, this.TextScale * this.Scale, SpriteEffects.None, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.Draw(time, batch, alpha, blendState, samplerState, matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Replaces this text field's text with the given text.
|
|
||||||
/// If the resulting <see cref="Text"/> exceeds <see cref="MaximumCharacters"/>, the end will be cropped to fit.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The new text</param>
|
|
||||||
/// <param name="removeMismatching">If any characters that don't match the <see cref="InputRule"/> should be left out</param>
|
|
||||||
public void SetText(object text, bool removeMismatching = false) {
|
|
||||||
var strg = text?.ToString() ?? string.Empty;
|
|
||||||
if (removeMismatching) {
|
|
||||||
var result = new StringBuilder();
|
|
||||||
foreach (var c in strg) {
|
|
||||||
if (this.InputRule(this, c.ToCachedString()))
|
|
||||||
result.Append(c);
|
|
||||||
}
|
|
||||||
strg = result.ToString();
|
|
||||||
} else if (!this.InputRule(this, strg))
|
|
||||||
return;
|
|
||||||
if (this.MaximumCharacters != null && strg.Length > this.MaximumCharacters)
|
|
||||||
strg = strg.Substring(0, this.MaximumCharacters.Value);
|
|
||||||
this.text.Clear();
|
|
||||||
this.text.Append(strg);
|
|
||||||
this.CaretPos = this.text.Length;
|
|
||||||
this.HandleTextChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Inserts the given text at the <see cref="CaretPos"/>.
|
|
||||||
/// If the resulting <see cref="Text"/> exceeds <see cref="MaximumCharacters"/>, the end will be cropped to fit.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The text to insert</param>
|
|
||||||
public void InsertText(object text) {
|
|
||||||
var strg = text.ToString();
|
|
||||||
if (!this.InputRule(this, strg))
|
|
||||||
return;
|
|
||||||
if (this.MaximumCharacters != null && this.text.Length + strg.Length > this.MaximumCharacters)
|
|
||||||
strg = strg.Substring(0, this.MaximumCharacters.Value - this.text.Length);
|
|
||||||
this.text.Insert(this.CaretPos, strg);
|
|
||||||
this.CaretPos += strg.Length;
|
|
||||||
this.HandleTextChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the given amount of text at the given index
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">The index</param>
|
|
||||||
/// <param name="length">The amount of text to remove</param>
|
|
||||||
public void RemoveText(int index, int length) {
|
|
||||||
if (index < 0 || index >= this.text.Length)
|
|
||||||
return;
|
|
||||||
this.text.Remove(index, length);
|
|
||||||
// ensure that caret pos is still in bounds
|
|
||||||
this.CaretPos = this.CaretPos;
|
|
||||||
this.HandleTextChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void InitStyle(UiStyle style) {
|
|
||||||
base.InitStyle(style);
|
|
||||||
this.TextScale.SetFromStyle(style.TextScale);
|
|
||||||
this.Font.SetFromStyle(style.Font);
|
|
||||||
this.Texture.SetFromStyle(style.TextFieldTexture);
|
|
||||||
this.HoveredTexture.SetFromStyle(style.TextFieldHoveredTexture);
|
|
||||||
this.HoveredColor.SetFromStyle(style.TextFieldHoveredColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Loading…
Reference in a new issue