diff --git a/MLEM.Extended/Extensions/BitmapFontExtensions.cs b/MLEM.Extended/Extensions/BitmapFontExtensions.cs index 44edf0b..365c9be 100644 --- a/MLEM.Extended/Extensions/BitmapFontExtensions.cs +++ b/MLEM.Extended/Extensions/BitmapFontExtensions.cs @@ -11,5 +11,9 @@ namespace MLEM.Extended.Extensions { return SpriteFontExtensions.SplitString(s => font.MeasureString(s).Width, text, width, scale); } + public static string TruncateString(this BitmapFont font, string text, float width, float scale, bool fromBack = false) { + return SpriteFontExtensions.TruncateString(s => font.MeasureString(s).Width, text, width, scale, fromBack); + } + } } \ No newline at end of file diff --git a/MLEM.Extended/Font/GenericBitmapFont.cs b/MLEM.Extended/Font/GenericBitmapFont.cs index 6aa793d..f4845e8 100644 --- a/MLEM.Extended/Font/GenericBitmapFont.cs +++ b/MLEM.Extended/Font/GenericBitmapFont.cs @@ -56,5 +56,9 @@ namespace MLEM.Extended.Font { return this.Font.SplitString(text, width, scale); } + public string TruncateString(string text, float width, float scale, bool fromBack = false) { + return this.Font.TruncateString(text, width, scale, fromBack); + } + } } \ No newline at end of file diff --git a/MLEM.Ui/Elements/TextField.cs b/MLEM.Ui/Elements/TextField.cs index 11303be..932bbe1 100644 --- a/MLEM.Ui/Elements/TextField.cs +++ b/MLEM.Ui/Elements/TextField.cs @@ -29,8 +29,8 @@ namespace MLEM.Ui.Elements { public float TextOffsetX = 4; private IGenericFont font; private double caretBlinkTimer; - private int textStartIndex; - private int textDisplayLength; + private string displayedText; + private int textOffset; public Rule InputRule; public string MobileTitle; public string MobileDescription; @@ -57,8 +57,10 @@ namespace MLEM.Ui.Elements { if (!this.IsSelected) return; if (key == Keys.Back) { - this.CaretPos--; - this.RemoveText(this.CaretPos, 1); + if (this.CaretPos > 0) { + this.CaretPos--; + this.RemoveText(this.CaretPos, 1); + } } else if (key == Keys.Delete) { this.RemoveText(this.CaretPos, 1); } else { @@ -81,19 +83,27 @@ namespace MLEM.Ui.Elements { private void HandleTextChange(bool textChanged = true) { // not initialized yet - if (this.font == null) { - this.textDisplayLength = this.text.Length; + if (this.font == null) return; - } var length = this.font.MeasureString(this.text).X * this.TextScale; var maxWidth = this.DisplayArea.Width / this.Scale - this.TextOffsetX * 2; if (length > maxWidth) { - // TODO - this.textStartIndex = 0; - this.textDisplayLength = this.text.Length; + // if we're moving the caret to the left + if (this.textOffset > this.CaretPos) { + this.textOffset = this.CaretPos; + } else { + // if we're moving the caret to the right + var importantArea = this.text.ToString(this.textOffset, Math.Min(this.CaretPos, this.text.Length) - this.textOffset); + var bound = this.CaretPos - this.font.TruncateString(importantArea, maxWidth, this.TextScale, true).Length; + if (this.textOffset < bound) { + this.textOffset = bound; + } + } + var visible = this.text.ToString(this.textOffset, this.text.Length - this.textOffset); + this.displayedText = this.font.TruncateString(visible, maxWidth, this.TextScale); } else { - this.textStartIndex = 0; - this.textDisplayLength = this.text.Length; + this.displayedText = this.Text; + this.textOffset = 0; } if (textChanged) @@ -103,6 +113,10 @@ namespace MLEM.Ui.Elements { public override void Update(GameTime time) { base.Update(time); + // handle first initialization if not done + if (this.displayedText == null) + this.HandleTextChange(false); + if (this.Input.IsKeyPressed(Keys.Left)) { this.CaretPos--; } else if (this.Input.IsKeyPressed(Keys.Right)) { @@ -131,7 +145,7 @@ namespace MLEM.Ui.Elements { var textPos = this.DisplayArea.Location.ToVector2() + new Vector2(this.TextOffsetX * this.Scale, this.DisplayArea.Height / 2); if (this.text.Length > 0 || this.IsSelected) { var caret = this.IsSelected ? this.caretBlinkTimer >= 0.5F ? "|" : " " : ""; - var display = this.text.ToString(this.textStartIndex, this.textDisplayLength).Insert(this.CaretPos - this.textStartIndex, caret); + var display = this.displayedText.Insert(this.CaretPos - this.textOffset, caret); this.font.DrawCenteredString(batch, display, textPos, this.TextScale * this.Scale, Color.White * alpha, false, true); } else if (this.PlaceholderText != null) { this.font.DrawCenteredString(batch, this.PlaceholderText, textPos, this.TextScale * this.Scale, Color.Gray * alpha, false, true); diff --git a/MLEM.Ui/Style/UntexturedStyle.cs b/MLEM.Ui/Style/UntexturedStyle.cs index 59c2159..b436b7d 100644 --- a/MLEM.Ui/Style/UntexturedStyle.cs +++ b/MLEM.Ui/Style/UntexturedStyle.cs @@ -82,6 +82,10 @@ namespace MLEM.Ui.Style { return text; } + public string TruncateString(string text, float width, float scale, bool fromBack = false) { + return text; + } + } } diff --git a/MLEM/Extensions/SpriteFontExtensions.cs b/MLEM/Extensions/SpriteFontExtensions.cs index 37c82fb..bc914d8 100644 --- a/MLEM/Extensions/SpriteFontExtensions.cs +++ b/MLEM/Extensions/SpriteFontExtensions.cs @@ -10,6 +10,25 @@ namespace MLEM.Extensions { return SplitString(s => font.MeasureString(s).X, text, width, scale); } + public static string TruncateString(this SpriteFont font, string text, float width, float scale, bool fromBack = false) { + return TruncateString(s => font.MeasureString(s).X, text, width, scale, fromBack); + } + + public static string TruncateString(Func widthFunc, string text, float width, float scale, bool fromBack = false) { + var total = new StringBuilder(); + for (var i = 0; i < text.Length; i++) { + if (fromBack) { + total.Insert(0, text[text.Length - 1 - i]); + } else { + total.Append(text[i]); + } + + if (widthFunc(total) * scale >= width) + return total.ToString(fromBack ? 1 : 0, total.Length - 1); + } + return total.ToString(); + } + public static string SplitString(Func widthFunc, string text, float width, float scale) { var total = new StringBuilder(); foreach (var line in text.Split('\n')) { diff --git a/MLEM/Font/GenericSpriteFont.cs b/MLEM/Font/GenericSpriteFont.cs index 3ee8280..ebf0e77 100644 --- a/MLEM/Font/GenericSpriteFont.cs +++ b/MLEM/Font/GenericSpriteFont.cs @@ -54,5 +54,9 @@ namespace MLEM.Font { return this.Font.SplitString(text, width, scale); } + public string TruncateString(string text, float width, float scale, bool fromBack = false) { + return this.Font.TruncateString(text, width, scale, fromBack); + } + } } \ No newline at end of file diff --git a/MLEM/Font/IGenericFont.cs b/MLEM/Font/IGenericFont.cs index 5b7d77f..0ce0de2 100644 --- a/MLEM/Font/IGenericFont.cs +++ b/MLEM/Font/IGenericFont.cs @@ -28,5 +28,7 @@ namespace MLEM.Font { string SplitString(string text, float width, float scale); + string TruncateString(string text, float width, float scale, bool fromBack = false); + } } \ No newline at end of file