diff --git a/Robust.Client/UserInterface/Controls/LineEdit.cs b/Robust.Client/UserInterface/Controls/LineEdit.cs index dd3a49a85f3..78ff5b18c58 100644 --- a/Robust.Client/UserInterface/Controls/LineEdit.cs +++ b/Robust.Client/UserInterface/Controls/LineEdit.cs @@ -29,6 +29,13 @@ public class LineEdit : Control public const string StylePropertyStyleBox = "stylebox"; public const string StylePropertyCursorColor = "cursor-color"; public const string StylePropertySelectionColor = "selection-color"; + + public const string StylePseudoClassNormal = "normal"; + public const string StylePseudoClassHover = "hover"; + public const string StylePseudoClassFocus = "focus"; + public const string StylePseudoClassNotEditable = "notEditable"; + + [Obsolete("Use StylePseudoClassNotEditable instead")] public const string StyleClassLineEditNotEditable = "notEditable"; public const string StylePseudoClassPlaceholder = "placeholder"; @@ -46,6 +53,16 @@ public class LineEdit : Control private TextEditShared.CursorBlink _blink; private readonly LineEditRenderBox _renderBox; + private bool Hovered + { + get; + set + { + field = value; + _updatePseudoClass(); + } + } + private bool _mouseSelectingText; private float _lastMousePosition; @@ -140,16 +157,9 @@ public bool Editable set { _editable = value; - if (_editable) - { - DefaultCursorShape = CursorShape.IBeam; - RemoveStyleClass(StyleClassLineEditNotEditable); - } - else - { - DefaultCursorShape = CursorShape.Arrow; - AddStyleClass(StyleClassLineEditNotEditable); - } + DefaultCursorShape = _editable ? CursorShape.IBeam : CursorShape.Arrow; + + _updatePseudoClass(); } } @@ -194,7 +204,20 @@ public int SelectionStart public int SelectionLower => Math.Min(_selectionStart, _cursorPosition); public int SelectionUpper => Math.Max(_selectionStart, _cursorPosition); - public bool HidePlaceHolderOnFocus { get; set; } + public bool HidePlaceHolderOnFocus + { + get; + set + { + if (field == value) + { + return; + } + + field = value; + _updatePseudoClass(); + } + } public bool IgnoreNext { get; set; } @@ -227,6 +250,7 @@ public LineEdit() DefaultCursorShape = CursorShape.IBeam; AddChild(_renderBox = new LineEditRenderBox(this)); + _updatePseudoClass(); } public void Clear() @@ -790,6 +814,20 @@ protected internal override void MouseMove(GUIMouseMoveEventArgs args) _lastMousePosition = args.RelativePosition.X; } + protected internal override void MouseEntered() + { + base.MouseEntered(); + + Hovered = true; + } + + protected internal override void MouseExited() + { + base.MouseExited(); + + Hovered = false; + } + private int GetIndexAtPos(float horizontalPos) { var style = _getStyleBox(); @@ -888,6 +926,8 @@ protected internal override void KeyboardFocusEntered() CursorPosition = _text.Length; SelectionStart = 0; } + + _updatePseudoClass(); } protected internal override void KeyboardFocusExited() @@ -899,6 +939,7 @@ protected internal override void KeyboardFocusExited() Root?.Window?.TextInputStop(); AbortIme(delete: false); + _updatePseudoClass(); } [Pure] @@ -941,7 +982,37 @@ private Color _getFontColor() private void _updatePseudoClass() { - SetOnlyStylePseudoClass(IsPlaceHolderVisible ? StylePseudoClassPlaceholder : null); + if (HasKeyboardFocus()) + { + SetOnlyStylePseudoClass(StylePseudoClassFocus); + } + else if (Hovered) + { + SetOnlyStylePseudoClass(StylePseudoClassHover); + } + else + { + SetOnlyStylePseudoClass(StylePseudoClassNormal); + } + + if (!Editable) + { + SetOnlyStylePseudoClass(StylePseudoClassNotEditable); +#pragma warning disable CS0618 + AddStyleClass(StyleClassLineEditNotEditable); +#pragma warning restore CS0618 + } + else + { +#pragma warning disable CS0618 + RemoveStyleClass(StyleClassLineEditNotEditable); +#pragma warning restore CS0618 + } + + if (IsPlaceHolderVisible) + { + AddStylePseudoClass(StylePseudoClassPlaceholder); + } } protected internal override void Draw(DrawingHandleScreen handle) diff --git a/Robust.Client/UserInterface/Controls/TextEdit.cs b/Robust.Client/UserInterface/Controls/TextEdit.cs index 4633b995d8e..34dfb0a1a48 100644 --- a/Robust.Client/UserInterface/Controls/TextEdit.cs +++ b/Robust.Client/UserInterface/Controls/TextEdit.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Frozen; using System.Collections.Generic; using System.Diagnostics.Contracts; @@ -41,7 +41,12 @@ public sealed class TextEdit : Control // @formatter:off public const string StylePropertyCursorColor = "cursor-color"; public const string StylePropertySelectionColor = "selection-color"; + + public const string StylePseudoClassNormal = "normal"; + public const string StylePseudoClassHover = "hover"; + public const string StylePseudoClassFocus = "focus"; public const string StylePseudoClassNotEditable = "notEditable"; + public const string StylePseudoClassPlaceholder = "placeholder"; // @formatter:on @@ -84,6 +89,19 @@ public sealed class TextEdit : Control private bool _mouseSelectingText; private Vector2 _lastMouseSelectPos; + private bool Hovered + { + get; + set + { + if (field == value) + return; + + field = value; + UpdatePseudoClass(); + } + } + // Debug overlay stuff. internal bool DebugOverlay; private Vector2? _lastDebugMousePos; @@ -101,6 +119,8 @@ public TextEdit() KeyboardFocusOnClick = true; MouseFilter = MouseFilterMode.Stop; DefaultCursorShape = CursorShape.IBeam; + + UpdatePseudoClass(); } /// @@ -1096,11 +1116,19 @@ private int GetStartOfLine(int lineIndex) return _lineBreaks[lineIndex - 1]; } + protected internal override void MouseEntered() + { + base.MouseEntered(); + + Hovered = true; + } + protected internal override void MouseExited() { base.MouseExited(); _lastDebugMousePos = null; + Hovered = false; } protected internal override void MouseMove(GUIMouseMoveEventArgs args) @@ -1172,9 +1200,25 @@ private void EnsureCursorVisible() private void UpdatePseudoClass() { - SetOnlyStylePseudoClass(IsPlaceholderVisible ? StylePseudoClassPlaceholder : null); if (!Editable) - AddStylePseudoClass(StylePseudoClassNotEditable); + { + SetOnlyStylePseudoClass(StylePseudoClassNotEditable); + } + else if (HasKeyboardFocus()) + { + SetOnlyStylePseudoClass(StylePseudoClassFocus); + } + else if (Hovered) + { + SetOnlyStylePseudoClass(StylePseudoClassHover); + } + else + { + SetOnlyStylePseudoClass(StylePseudoClassNormal); + } + + if (IsPlaceholderVisible) + AddStylePseudoClass(StylePseudoClassPlaceholder); } @@ -1447,6 +1491,8 @@ protected internal override void KeyboardFocusEntered() { Root?.Window?.TextInputStart(); } + + UpdatePseudoClass(); } protected internal override void KeyboardFocusExited() @@ -1455,6 +1501,8 @@ protected internal override void KeyboardFocusExited() Root?.Window?.TextInputStop(); AbortIme(delete: false); + + UpdatePseudoClass(); } public sealed class TextEditEventArgs(TextEdit control, Rope.Node textRope) : EventArgs diff --git a/Robust.Client/UserInterface/UserInterfaceManager.Input.cs b/Robust.Client/UserInterface/UserInterfaceManager.Input.cs index 274aa2abc00..89a507b25ac 100644 --- a/Robust.Client/UserInterface/UserInterfaceManager.Input.cs +++ b/Robust.Client/UserInterface/UserInterfaceManager.Input.cs @@ -516,8 +516,8 @@ public void GrabKeyboardFocus(Control control) public void ReleaseKeyboardFocus() { var oldFocused = KeyboardFocused; - oldFocused?.KeyboardFocusExited(); KeyboardFocused = null; + oldFocused?.KeyboardFocusExited(); } public void ReleaseKeyboardFocus(Control ifControl)