Use enums for ActionTypes in InputField, use ReadOnlySpan<char> for Font measurements, only measure placeholderSize if the input is empty.
This commit is contained in:
@@ -83,16 +83,26 @@ public class Font : Resource, IUpdatableResource, IDisposable
|
|||||||
/// <returns>A <see cref="Rect"/> with the sizes of a given text using this font.</returns>
|
/// <returns>A <see cref="Rect"/> with the sizes of a given text using this font.</returns>
|
||||||
public Rect Measure(string text)
|
public Rect Measure(string text)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(text))
|
return Measure(text.AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Measures a given <see cref="ReadOnlySpan"/> of characters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chars"></param>
|
||||||
|
/// <returns>A <see cref="Rect"/> with the sizes of a given text using this font.</returns>
|
||||||
|
public Rect Measure(ReadOnlySpan<char> chars)
|
||||||
|
{
|
||||||
|
if (chars.Length == 0)
|
||||||
return Rect.Zero;
|
return Rect.Zero;
|
||||||
|
|
||||||
float totalWidth = 0;
|
float totalWidth = 0;
|
||||||
float maxAscent = 0;
|
float maxAscent = 0;
|
||||||
float maxDescent = 0;
|
float maxDescent = 0;
|
||||||
|
|
||||||
for (int i = 0; i < text.Length; i++)
|
for (int i = 0; i < chars.Length; i++)
|
||||||
{
|
{
|
||||||
char c = text[i];
|
char c = chars[i];
|
||||||
Glyph glyph = GetGlyph(c);
|
Glyph glyph = GetGlyph(c);
|
||||||
|
|
||||||
totalWidth += glyph.Advance * SpacingScale + LetterSpacing;
|
totalWidth += glyph.Advance * SpacingScale + LetterSpacing;
|
||||||
@@ -107,7 +117,7 @@ public class Font : Resource, IUpdatableResource, IDisposable
|
|||||||
|
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
char prevChar = text[i - 1];
|
char prevChar = chars[i - 1];
|
||||||
totalWidth += GetKerning(prevChar, c);
|
totalWidth += GetKerning(prevChar, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ namespace Voile.UI.Widgets;
|
|||||||
|
|
||||||
public class InputField : Widget, ITickableElement
|
public class InputField : Widget, ITickableElement
|
||||||
{
|
{
|
||||||
|
enum ActionType { None, Backspace, Left, Right }
|
||||||
|
|
||||||
public override Rect MinimumSize => _placeholderSize + _padding;
|
public override Rect MinimumSize => _placeholderSize + _padding;
|
||||||
public override string? StyleElementName => nameof(InputField);
|
public override string? StyleElementName => nameof(InputField);
|
||||||
|
|
||||||
@@ -58,7 +60,7 @@ public class InputField : Widget, ITickableElement
|
|||||||
|
|
||||||
if (!_isFocused)
|
if (!_isFocused)
|
||||||
{
|
{
|
||||||
_lastActiveAction = string.Empty;
|
_lastActiveAction = ActionType.None;
|
||||||
_repeatTimer = 0.0f;
|
_repeatTimer = 0.0f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -100,15 +102,15 @@ public class InputField : Widget, ITickableElement
|
|||||||
|
|
||||||
private void HandleRepeatingActions(float dt, InputSystem input)
|
private void HandleRepeatingActions(float dt, InputSystem input)
|
||||||
{
|
{
|
||||||
string currentAction = string.Empty;
|
ActionType currentAction = ActionType.None;
|
||||||
|
|
||||||
if (input.IsKeyboardKeyDown(KeyboardKey.Backspace)) currentAction = "backspace";
|
if (input.IsKeyboardKeyDown(KeyboardKey.Backspace)) currentAction = ActionType.Backspace;
|
||||||
else if (input.IsKeyboardKeyDown(KeyboardKey.Left)) currentAction = "left";
|
else if (input.IsKeyboardKeyDown(KeyboardKey.Left)) currentAction = ActionType.Left;
|
||||||
else if (input.IsKeyboardKeyDown(KeyboardKey.Right)) currentAction = "right";
|
else if (input.IsKeyboardKeyDown(KeyboardKey.Right)) currentAction = ActionType.Right;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(currentAction))
|
if (currentAction == ActionType.None)
|
||||||
{
|
{
|
||||||
_lastActiveAction = string.Empty;
|
_lastActiveAction = ActionType.None;
|
||||||
_repeatTimer = 0.0f;
|
_repeatTimer = 0.0f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -138,11 +140,11 @@ public class InputField : Widget, ITickableElement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteAction(string actionName)
|
private void ExecuteAction(ActionType action)
|
||||||
{
|
{
|
||||||
switch (actionName)
|
switch (action)
|
||||||
{
|
{
|
||||||
case "backspace":
|
case ActionType.Backspace:
|
||||||
if (_cursor > 0 && _input.Length > 0)
|
if (_cursor > 0 && _input.Length > 0)
|
||||||
{
|
{
|
||||||
_input = _input.Remove(_cursor - 1, 1);
|
_input = _input.Remove(_cursor - 1, 1);
|
||||||
@@ -151,7 +153,7 @@ public class InputField : Widget, ITickableElement
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "left":
|
case ActionType.Left:
|
||||||
if (_cursor > 0)
|
if (_cursor > 0)
|
||||||
{
|
{
|
||||||
_cursor--;
|
_cursor--;
|
||||||
@@ -159,7 +161,7 @@ public class InputField : Widget, ITickableElement
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "right":
|
case ActionType.Right:
|
||||||
if (_cursor < _input.Length)
|
if (_cursor < _input.Length)
|
||||||
{
|
{
|
||||||
_cursor++;
|
_cursor++;
|
||||||
@@ -211,7 +213,7 @@ public class InputField : Widget, ITickableElement
|
|||||||
// Caret
|
// Caret
|
||||||
if (_isFocused && _blink)
|
if (_isFocused && _blink)
|
||||||
{
|
{
|
||||||
var caretX = MeasureTextWidth(_input.Substring(0, _cursor));
|
var caretX = MeasureTextWidth(_input.AsSpan(0, _cursor));
|
||||||
|
|
||||||
renderer.SetTransform(
|
renderer.SetTransform(
|
||||||
new Vector2(GlobalPosition.X + caretX + _padding.Left, GlobalPosition.Y + _padding.Top),
|
new Vector2(GlobalPosition.X + caretX + _padding.Left, GlobalPosition.Y + _padding.Top),
|
||||||
@@ -247,6 +249,8 @@ public class InputField : Widget, ITickableElement
|
|||||||
var font = _suitableFont.Value;
|
var font = _suitableFont.Value;
|
||||||
|
|
||||||
_textSize = font.Measure(_input);
|
_textSize = font.Measure(_input);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(_input))
|
||||||
_placeholderSize = font.Measure(PlaceholderText);
|
_placeholderSize = font.Measure(PlaceholderText);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,18 +259,18 @@ public class InputField : Widget, ITickableElement
|
|||||||
Size = _padding + size;
|
Size = _padding + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float MeasureTextWidth(string text)
|
private float MeasureTextWidth(ReadOnlySpan<char> chars)
|
||||||
{
|
{
|
||||||
if (!_suitableFont.HasValue)
|
if (!_suitableFont.HasValue)
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _suitableFont.Value.Measure(text).Width;
|
return _suitableFont.Value.Measure(chars).Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float _repeatTimer = 0.0f;
|
private float _repeatTimer = 0.0f;
|
||||||
private string _lastActiveAction = string.Empty;
|
private ActionType _lastActiveAction = ActionType.None;
|
||||||
private const float INITIAL_DELAY = 0.5f;
|
private const float INITIAL_DELAY = 0.5f;
|
||||||
private const float REPEAT_RATE = 0.05f;
|
private const float REPEAT_RATE = 0.05f;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user