Element styling, rename IsMousePressed to IsMouseButtonPressed in InputSystem, Button widget.
This commit is contained in:
@@ -19,7 +19,7 @@ public class TestGame : Game
|
||||
{
|
||||
InitializeSystemsDefault();
|
||||
|
||||
_uiSystem = new UISystem(Input, ResourceRef<Style>.Empty());
|
||||
_uiSystem = new UISystem(Input, StyleSheet.Default);
|
||||
// _uiSystem.RenderDebugRects = true;
|
||||
|
||||
_particleSystem = new ParticleSystem();
|
||||
@@ -64,7 +64,6 @@ public class TestGame : Game
|
||||
_emitterId = _particleSystem.CreateEmitter(Renderer.WindowSize / 2, _fireEffect);
|
||||
|
||||
var addButton = new Button("Add element", _defaultFontSet, () => { _container.AddChild(new Label("Hello, World!", _defaultFontSet)); });
|
||||
addButton.Padding = new Margin(8.0f);
|
||||
|
||||
var removeButton = new Button("Remove element", _defaultFontSet, () =>
|
||||
{
|
||||
@@ -73,21 +72,30 @@ public class TestGame : Game
|
||||
_container.RemoveChild(lastChild);
|
||||
});
|
||||
|
||||
removeButton.Padding = new Margin(8.0f);
|
||||
removeButton.StyleVariant = "Danger";
|
||||
|
||||
_buttonContainer.AddChild(addButton);
|
||||
_buttonContainer.AddChild(removeButton);
|
||||
// _buttonContainer.AddChild(addButton);
|
||||
// _buttonContainer.AddChild(removeButton);
|
||||
|
||||
var c = new VerticalContainer();
|
||||
var c = new HorizontalContainer()
|
||||
{
|
||||
StyleVariant = "Layer01",
|
||||
ConfineToContents = true,
|
||||
Anchor = Anchor.TopCenter
|
||||
};
|
||||
|
||||
var m = new MarginContainer();
|
||||
m.AddChild(_container);
|
||||
c.AddChild(addButton);
|
||||
c.AddChild(removeButton);
|
||||
|
||||
c.AddChild(_buttonContainer);
|
||||
c.AddChild(m);
|
||||
var vc = new VerticalContainer(0.0f);
|
||||
vc.AddChild(c);
|
||||
|
||||
_rootFill.AddChild(c);
|
||||
var f = new MarginContainer(new Margin(0.0f));
|
||||
f.AddChild(_container);
|
||||
|
||||
vc.AddChild(f);
|
||||
|
||||
_rootFill.AddChild(vc);
|
||||
_uiSystem.AddElement(_rootFill);
|
||||
}
|
||||
|
||||
@@ -152,7 +160,8 @@ public class TestGame : Game
|
||||
Justify = JustifyContent.Start,
|
||||
Align = AlignItems.Center,
|
||||
Wrap = true,
|
||||
Gap = 8.0f
|
||||
Gap = 8.0f,
|
||||
StyleVariant = "Layer02",
|
||||
};
|
||||
|
||||
[NotNull] private Label _label;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Voile.Input
|
||||
|
||||
public bool IsPressed(InputSystem inputSystem)
|
||||
{
|
||||
return inputSystem.IsMousePressed(MouseButton);
|
||||
return inputSystem.IsMouseButtonPressed(MouseButton);
|
||||
}
|
||||
|
||||
public bool IsDown(InputSystem inputSystem)
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Voile.Input
|
||||
|
||||
public abstract int GetCharPressed();
|
||||
|
||||
public abstract bool IsMousePressed(MouseButton button);
|
||||
public abstract bool IsMouseButtonPressed(MouseButton button);
|
||||
public abstract bool IsMouseButtonDown(MouseButton button);
|
||||
public abstract bool IsMouseButtonReleased(MouseButton button);
|
||||
public abstract float GetMouseWheelMovement();
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Voile.Input
|
||||
public override bool KeyboardKeyJustPressed(KeyboardKey key) => _justPressedKeys.Contains(key);
|
||||
public override bool KeyboardKeyJustReleased(KeyboardKey key) => _justReleasedKeys.Contains(key);
|
||||
|
||||
public override bool IsMousePressed(MouseButton button) => _pressedMouseButtons.Contains(button);
|
||||
public override bool IsMouseButtonPressed(MouseButton button) => _pressedMouseButtons.Contains(button);
|
||||
public override bool IsMouseButtonReleased(MouseButton button) => _releasedMouseButtons.Contains(button);
|
||||
public override bool IsMouseButtonDown(MouseButton button) => _downMouseButtons.Contains(button);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ public abstract class Container : UIElement, IParentableElement
|
||||
/// </summary>
|
||||
public bool ConfineToContents { get; set; } = false;
|
||||
|
||||
public override string? StyleElementName => nameof(Container);
|
||||
|
||||
public override Rect MinimumSize => _minimumSize;
|
||||
|
||||
public Container()
|
||||
@@ -122,6 +124,7 @@ public abstract class Container : UIElement, IParentableElement
|
||||
|
||||
public void AddChild(UIElement child)
|
||||
{
|
||||
// child.StyleSheetOverride = StyleSheet;
|
||||
_children.Add(child);
|
||||
child.SetParent(this);
|
||||
|
||||
@@ -139,10 +142,21 @@ public abstract class Container : UIElement, IParentableElement
|
||||
|
||||
public override void Render(RenderSystem renderer, Style style)
|
||||
{
|
||||
var backgroundColor = style.BackgroundColor;
|
||||
|
||||
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
||||
renderer.DrawRectangle(new Vector2(Size.Width, Size.Height), backgroundColor);
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (child is not IRenderableElement renderable) continue;
|
||||
renderable.Render(renderer, style);
|
||||
|
||||
if (!child.TryGetStyle(StyleSheet, out var childStyle))
|
||||
{
|
||||
childStyle = new Style();
|
||||
}
|
||||
|
||||
renderable.Render(renderer, childStyle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ public class FillContainer : Container
|
||||
{
|
||||
base.OnUpdate();
|
||||
Size = _lastParentSize;
|
||||
|
||||
if (Children.Count != 0)
|
||||
{
|
||||
Children[0].Size = Size;
|
||||
}
|
||||
}
|
||||
|
||||
private Rect _lastParentSize = Rect.Zero;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Voile.UI.Containers;
|
||||
/// <summary>
|
||||
/// Represents the margin offsets applied around an element.
|
||||
/// </summary>
|
||||
public struct Margin
|
||||
public struct Margin : IEquatable<Margin>
|
||||
{
|
||||
public float Left;
|
||||
public float Right;
|
||||
@@ -39,6 +39,25 @@ public struct Margin
|
||||
|
||||
public static Rect operator +(Rect rect, Margin margin) =>
|
||||
margin + rect;
|
||||
|
||||
|
||||
public static bool operator ==(Margin a, Margin b) =>
|
||||
a.Equals(b);
|
||||
|
||||
public static bool operator !=(Margin a, Margin b) =>
|
||||
!a.Equals(b);
|
||||
|
||||
public bool Equals(Margin other) =>
|
||||
Left == other.Left &&
|
||||
Right == other.Right &&
|
||||
Top == other.Top &&
|
||||
Bottom == other.Bottom;
|
||||
|
||||
public override bool Equals(object? obj) =>
|
||||
obj is Margin other && Equals(other);
|
||||
|
||||
public override int GetHashCode() =>
|
||||
HashCode.Combine(Left, Right, Top, Bottom);
|
||||
}
|
||||
|
||||
public class MarginContainer : Container
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Voile.Resources;
|
||||
using Voile.UI.Containers;
|
||||
|
||||
namespace Voile.UI;
|
||||
|
||||
@@ -10,4 +12,103 @@ public class Style : TextDataResource
|
||||
public Style(string path) : base(path)
|
||||
{
|
||||
}
|
||||
|
||||
public Style() : base(string.Empty) { }
|
||||
|
||||
public Margin Padding { get; set; }
|
||||
public Color BackgroundColor { get; set; }
|
||||
public Margin BorderSize { get; set; }
|
||||
public Color BorderColor { get; set; }
|
||||
public float CornerRadius { get; set; }
|
||||
public Color TextColor { get; set; } = Color.White;
|
||||
}
|
||||
|
||||
public class StyleSheet : TextDataResource
|
||||
{
|
||||
public StyleSheet(string path) : base(path)
|
||||
{
|
||||
}
|
||||
|
||||
public StyleSheet(Dictionary<string, Style> styles) : base(string.Empty)
|
||||
{
|
||||
_styles = styles;
|
||||
}
|
||||
|
||||
public bool TryGet(string styleName, [NotNullWhen(true)] out Style? style)
|
||||
{
|
||||
return _styles.TryGetValue(styleName, out style);
|
||||
}
|
||||
|
||||
public static StyleSheet Default => new(new Dictionary<string, Style>()
|
||||
{
|
||||
{"Label", new Style()
|
||||
{
|
||||
TextColor = Color.FromHexString("#161616"),
|
||||
}},
|
||||
{ "Button", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#0f62fe"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Normal", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#0f62fe"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Hovered", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#0353e9"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Pressed", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#002d9c"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Danger", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#da1e28"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Danger.Normal", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#da1e28"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Danger.Hovered", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#ba1b23"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Button.Danger.Pressed", new Style()
|
||||
{
|
||||
Padding = new Margin(8.0f),
|
||||
BackgroundColor = Color.FromHexString("#750e13"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Container", new Style()
|
||||
{
|
||||
BackgroundColor = Color.FromHexString("#ffffff"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Container.Layer01", new Style()
|
||||
{
|
||||
BackgroundColor = Color.FromHexString("#f4f4f4"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
{"Container.Layer02", new Style()
|
||||
{
|
||||
BackgroundColor = Color.FromHexString("#e8e8e8"),
|
||||
TextColor = Color.FromHexString("#ffffff"),
|
||||
}},
|
||||
});
|
||||
|
||||
private Dictionary<string, Style> _styles = new();
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Voile.Rendering;
|
||||
|
||||
namespace Voile.UI;
|
||||
@@ -13,6 +15,23 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
|
||||
public Vector2 LocalPosition { get; set; } = Vector2.Zero;
|
||||
public Vector2 GlobalPosition => _parent?.GlobalPosition + LocalPosition ?? LocalPosition;
|
||||
|
||||
public string StyleName => $"{StyleElementName ?? "UIElement"}{GetStyleVariantString()}{ConstructStyleModifiers(StyleModifiers)}";
|
||||
|
||||
/// <summary>
|
||||
/// An element name for style.
|
||||
/// </summary>
|
||||
public virtual string? StyleElementName { get; }
|
||||
|
||||
public string StyleVariant { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// List of style modifiers for this <see cref="UIElement"/>.
|
||||
/// </summary>
|
||||
public virtual string[]? StyleModifiers { get; }
|
||||
|
||||
public StyleSheet StyleSheet => Parent?.StyleSheet ?? StyleSheetOverride;
|
||||
public StyleSheet StyleSheetOverride { get; set; } = new(string.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Parent <see cref="UIElement"/> of this element.
|
||||
/// </summary>
|
||||
@@ -47,6 +66,11 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
|
||||
public abstract Rect MinimumSize { get; }
|
||||
public bool Dirty => _dirty;
|
||||
|
||||
public bool TryGetStyle(StyleSheet styleSheet, [NotNullWhen(true)] out Style? style)
|
||||
{
|
||||
return styleSheet.TryGet(StyleName, out style);
|
||||
}
|
||||
|
||||
public virtual void MarkDirty()
|
||||
{
|
||||
if (Parent != null && !Parent.Dirty)
|
||||
@@ -112,6 +136,30 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
|
||||
LocalPosition = Anchor.Calculate(parentPosition, parentRect, Size) + new Vector2(AnchorOffset.X, AnchorOffset.Y);
|
||||
}
|
||||
|
||||
private string ConstructStyleModifiers(string[]? modifiers)
|
||||
{
|
||||
if (modifiers == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (var modifier in modifiers)
|
||||
{
|
||||
sb.Append($".{modifier}");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private string GetStyleVariantString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(StyleVariant))
|
||||
return string.Empty;
|
||||
|
||||
return $".{StyleVariant}";
|
||||
}
|
||||
|
||||
private bool _dirty = true;
|
||||
private Rect _size = Rect.Zero;
|
||||
|
||||
|
||||
@@ -14,25 +14,26 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
|
||||
|
||||
public UISystem(InputSystem inputSystem)
|
||||
{
|
||||
_style = ResourceRef<Style>.Empty();
|
||||
_styleSheet = StyleSheet.Default;
|
||||
_input = inputSystem;
|
||||
}
|
||||
|
||||
public UISystem(InputSystem inputSystem, ResourceRef<Style> style)
|
||||
public UISystem(InputSystem inputSystem, StyleSheet styleSheet)
|
||||
{
|
||||
_input = inputSystem;
|
||||
_style = style;
|
||||
_styleSheet = styleSheet;
|
||||
}
|
||||
|
||||
public UISystem(InputSystem inputSystem, ResourceRef<Style> style, List<UIElement> elements)
|
||||
public UISystem(InputSystem inputSystem, StyleSheet styleSheet, List<UIElement> elements)
|
||||
{
|
||||
_input = inputSystem;
|
||||
_style = style;
|
||||
_styleSheet = styleSheet;
|
||||
_elements = elements;
|
||||
}
|
||||
|
||||
public void AddElement(UIElement element)
|
||||
{
|
||||
element.StyleSheetOverride = _styleSheet;
|
||||
_elements.Add(element);
|
||||
_inputElementIndices.Add(element.GlobalPosition, _elements.Count - 1);
|
||||
}
|
||||
@@ -40,30 +41,33 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
HandleInput();
|
||||
// HandleInput();
|
||||
}
|
||||
|
||||
public void Render(RenderSystem renderer)
|
||||
{
|
||||
// Update elements each time UI system is rendered.
|
||||
HandleInput();
|
||||
|
||||
foreach (var element in _elements)
|
||||
{
|
||||
if (element is not IUpdatableElement updatable) continue;
|
||||
updatable.Update();
|
||||
}
|
||||
|
||||
|
||||
foreach (var element in _elements)
|
||||
{
|
||||
if (element is IRenderableElement renderable)
|
||||
{
|
||||
// TODO: normally you'd load a default style if the one supplied is empty,
|
||||
// but for now this will do.
|
||||
if (!_style.TryGetValue(out var value))
|
||||
if (!_styleSheet.TryGet(element.StyleName, out var style))
|
||||
{
|
||||
value = new Style(string.Empty);
|
||||
style = new Style(string.Empty);
|
||||
}
|
||||
|
||||
renderable.Render(renderer, value);
|
||||
renderable.Render(renderer, style);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +142,7 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
|
||||
{
|
||||
MouseDown = _input.IsMouseButtonDown(MouseButton.Left),
|
||||
MouseReleased = _input.IsMouseButtonReleased(MouseButton.Left),
|
||||
MousePressed = _input.IsMouseButtonReleased(MouseButton.Left),
|
||||
MousePressed = _input.IsMouseButtonPressed(MouseButton.Left),
|
||||
};
|
||||
PropagateInput(_elements, context);
|
||||
}
|
||||
@@ -169,7 +173,7 @@ public class UISystem : IUpdatableSystem, IRenderableSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
private ResourceRef<Style> _style;
|
||||
private StyleSheet _styleSheet;
|
||||
private List<UIElement> _elements = new();
|
||||
private InputSystem _input;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Voile.Input;
|
||||
using Voile.Rendering;
|
||||
using Voile.Resources;
|
||||
using Voile.UI.Containers;
|
||||
@@ -27,13 +26,28 @@ public class Button : Widget
|
||||
MarkDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public ButtonState CurrentState { get; private set; } = ButtonState.Normal;
|
||||
|
||||
public override Rect MinimumSize => Padding + _textSize;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="FontSet"/> to use with this button.
|
||||
/// </summary>
|
||||
public FontSet FontSet { get; set; } = new();
|
||||
public Margin Padding { get; set; } = Margin.Zero;
|
||||
public Margin Padding
|
||||
{
|
||||
get => _padding; set
|
||||
{
|
||||
_padding = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string? StyleElementName => nameof(Button);
|
||||
public override string[]? StyleModifiers =>
|
||||
[
|
||||
CurrentState.ToString()
|
||||
];
|
||||
|
||||
public Button(string text, ResourceRef<Font> fontOverride, Action pressedAction)
|
||||
{
|
||||
@@ -60,20 +74,59 @@ public class Button : Widget
|
||||
public override void Render(RenderSystem renderer, Style style)
|
||||
{
|
||||
// TODO: use a button color from style.
|
||||
|
||||
var backgroundColor = style.BackgroundColor;
|
||||
|
||||
if (_padding != style.Padding)
|
||||
{
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
_padding = style.Padding;
|
||||
var textColor = style.TextColor;
|
||||
|
||||
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
||||
renderer.DrawRectangle(new Vector2(MinimumSize.Width, MinimumSize.Height), new Color(0.25f, 0.25f, 0.25f));
|
||||
renderer.DrawRectangle(new Vector2(Size.Width, Size.Height), backgroundColor);
|
||||
|
||||
var textPosition = new Vector2(GlobalPosition.X + Padding.Left, GlobalPosition.Y + Padding.Top);
|
||||
renderer.SetTransform(textPosition, Vector2.Zero);
|
||||
renderer.DrawText(_suitableFont, _text, Color.White);
|
||||
renderer.DrawText(_suitableFont, _text, textColor);
|
||||
}
|
||||
|
||||
protected override void OnInput(UIInputContext action)
|
||||
{
|
||||
if (action.MouseReleased && ContainsPoint(action.MousePosition))
|
||||
bool isHovering = ContainsPoint(action.MousePosition);
|
||||
|
||||
if (action.MousePressed && isHovering)
|
||||
{
|
||||
_isHeldDown = true;
|
||||
CurrentState = ButtonState.Pressed;
|
||||
}
|
||||
else if (action.MouseReleased)
|
||||
{
|
||||
if (_isHeldDown && isHovering)
|
||||
{
|
||||
_pressedAction?.Invoke();
|
||||
}
|
||||
|
||||
_isHeldDown = false;
|
||||
CurrentState = isHovering ? ButtonState.Hovered : ButtonState.Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isHeldDown)
|
||||
{
|
||||
CurrentState = ButtonState.Pressed; // keep showing as pressed
|
||||
}
|
||||
else if (isHovering)
|
||||
{
|
||||
CurrentState = ButtonState.Hovered;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentState = ButtonState.Normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
@@ -95,7 +148,7 @@ public class Button : Widget
|
||||
var font = _suitableFont.Value;
|
||||
_textSize = font.Measure(_text);
|
||||
|
||||
Size = Padding + _textSize;
|
||||
Size = _padding + _textSize;
|
||||
}
|
||||
|
||||
private Action _pressedAction;
|
||||
@@ -104,4 +157,8 @@ public class Button : Widget
|
||||
|
||||
private string _text = "Hello, World!";
|
||||
private Rect _textSize = Rect.Zero;
|
||||
|
||||
private Margin _padding;
|
||||
|
||||
private bool _isHeldDown;
|
||||
}
|
||||
@@ -18,6 +18,8 @@ public class Label : Widget
|
||||
}
|
||||
}
|
||||
|
||||
public override string? StyleElementName => nameof(Label);
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="FontSet"/> to use with this label.
|
||||
/// </summary>
|
||||
@@ -53,7 +55,7 @@ public class Label : Widget
|
||||
// TODO: use style here.
|
||||
|
||||
renderer.SetTransform(GlobalPosition, Vector2.Zero);
|
||||
renderer.DrawText(_suitableFont, _text, Color.White);
|
||||
renderer.DrawText(_suitableFont, _text, style.TextColor);
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
|
||||
@@ -29,11 +29,8 @@ public abstract class Widget : UIElement, IInputElement
|
||||
public void Input(UIInputContext context)
|
||||
{
|
||||
if (context.Handled || IgnoreInput) return;
|
||||
if (ContainsPoint(context.MousePosition))
|
||||
{
|
||||
OnInput(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when this widget receives input.
|
||||
|
||||
Reference in New Issue
Block a user