Files
RobustToolbox/Robust.Client/UserInterface/Controls/BaseButton.cs
ShadowCommander a8d6c294ab Input System Refactor (#840)
* Fixes right click menu stopping input

Removed a flag change when the modal stack was showing, which preventing the click from getting passed to the next function.

* Added parsing for mod2 and mod3 from Keybind YAML

* Fixes a crash on context change when a keybind is not defined in keybinds.yml

* Implemented ShowDebugConsole Hotkey

* Refactored input system

Refactored input system to run Key and Mouse input through the InputManager before doing stuff.

* Upgraded LineEdit and classes that use it. Fixed input while KeyboardFocused.

Upgraded LineEdit to use Keybinds.
Upgraded DebugConsole to use Keybinds.
Replaced all references to MouseDown, MouseUp, KeyDown, and KeyUp with KeyBindUp and KeyBindDown.
Moved UserInterfaceManager call from GameController.Input to InputManager event.
Stopped input going to simulation while a control has focus in UserInterfaceManager.

* Some fixes for input system

Fixed keybinds getting stuck when selecting a LineEdit.
Changed MenuBar to not error.
Fixed a few cases where LineEdit would eat input if you hovered over it and where mouse input got eaten when clicking in the world while a LineEdit was selected.

* Removed extra dependencies

* Added GUIBoundKeyEventArgs to ButtonEventArgs

* Fixes for input with LineEdit selected

Fixed multiple keybinds mapped to the same key not triggering.
Fixed keybind input not getting to LineEdit when hovering over a control.

* Implemented Key Repeat for LineEdit

* Fix for input on Robust.Lite Launcher

* Renames NonFocusKeybinds to EnableAllKeybinds

Renamed NonFocusKeybinds to EnableAllKeybinds and added comment to clarify usage

* Adds repeating keybinds

Used for TextBackspace, TextCursorLeft, and TextCursorRight
Reverts a change to LineEdit that implemented repeating keys
Adds some documentation comments
2019-08-21 17:13:48 +02:00

292 lines
8.1 KiB
C#

using System;
using Robust.Shared.Input;
using Robust.Shared.ViewVariables;
namespace Robust.Client.UserInterface.Controls
{
/// <summary>
/// Base class for a generic UI button.
/// </summary>
/// <seealso cref="Button"/>
/// <seealso cref="TextureButton"/>
/// <seealso cref="CheckBox"/>
public abstract class BaseButton : Control
{
private bool _attemptingPress;
private bool _beingHovered;
private bool _disabled;
private bool _pressed;
private bool _enableAllKeybinds;
/// <summary>
/// Controls mode of operation in relation to press/release events.
/// </summary>
[ViewVariables]
public ActionMode Mode { get; set; } = ActionMode.Release;
/// <summary>
/// Whether the button is disabled.
/// If a button is disabled, it appears greyed out and cannot be interacted with.
/// </summary>
[ViewVariables]
public bool Disabled
{
get => _disabled;
set
{
var old = _disabled;
_disabled = value;
if (old != value)
{
DrawModeChanged();
}
}
}
/// <summary>
/// Whether the button is currently toggled down. Only applies when <see cref="ToggleMode"/> is true.
/// </summary>
[ViewVariables]
public bool Pressed
{
get => _pressed;
set
{
if (_pressed == value)
{
return;
}
_pressed = value;
DrawModeChanged();
}
}
/// <summary>
/// Whether a button enables Keybinds without GUIBoundKeyEventArgs.CanFocus to trigger the button.
/// </summary>
public bool EnableAllKeybinds
{
get => _enableAllKeybinds;
set => _enableAllKeybinds = value;
}
/// <summary>
/// If <c>true</c>, this button functions as a toggle, not as a regular push button.
/// </summary>
[ViewVariables]
public bool ToggleMode { get; set; }
/// <summary>
/// If <c>true</c>, this button is currently being hovered over by the mouse.
/// </summary>
[ViewVariables]
public bool IsHovered => _beingHovered;
/// <summary>
/// Draw mode used for styling of buttons.
/// </summary>
[ViewVariables]
public DrawModeEnum DrawMode
{
get
{
if (Disabled)
{
return DrawModeEnum.Disabled;
}
if (Pressed || _attemptingPress)
{
return DrawModeEnum.Pressed;
}
if (IsHovered)
{
return DrawModeEnum.Hover;
}
return DrawModeEnum.Normal;
}
}
/// <summary>
/// Fired when the button is pushed down by the mouse.
/// </summary>
public event Action<ButtonEventArgs> OnButtonDown;
/// <summary>
/// Fired when the button is released by the mouse.
/// </summary>
public event Action<ButtonEventArgs> OnButtonUp;
/// <summary>
/// Fired when the button is "pressed". When this happens depends on <see cref="Mode"/>.
/// </summary>
public event Action<ButtonEventArgs> OnPressed;
/// <summary>
/// If <see cref="ToggleMode"/> is set, fired when the button is toggled up or down.
/// </summary>
public event Action<ButtonToggledEventArgs> OnToggled;
protected virtual void DrawModeChanged()
{
}
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.KeyBindDown(args);
if (Disabled || (!_enableAllKeybinds && !args.CanFocus))
{
return;
}
var buttonEventArgs = new ButtonEventArgs(this, args);
OnButtonDown?.Invoke(buttonEventArgs);
var drawMode = DrawMode;
if (Mode == ActionMode.Release)
{
_attemptingPress = true;
}
else
{
if (ToggleMode)
{
_pressed = !_pressed;
OnPressed?.Invoke(buttonEventArgs);
OnToggled?.Invoke(new ButtonToggledEventArgs(Pressed, this, args));
}
else
{
_attemptingPress = true;
OnPressed?.Invoke(buttonEventArgs);
}
}
if (drawMode != DrawMode)
{
DrawModeChanged();
}
}
protected internal override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.KeyBindUp(args);
if (Disabled)
{
return;
}
var buttonEventArgs = new ButtonEventArgs(this, args);
OnButtonUp?.Invoke(buttonEventArgs);
var drawMode = DrawMode;
if (Mode == ActionMode.Release && _attemptingPress)
{
if (ToggleMode)
{
_pressed = !_pressed;
}
OnPressed?.Invoke(buttonEventArgs);
if (ToggleMode && args.CanFocus)
{
OnToggled?.Invoke(new ButtonToggledEventArgs(Pressed, this, args));
}
}
_attemptingPress = false;
if (drawMode != DrawMode)
{
DrawModeChanged();
}
}
protected internal override void MouseEntered()
{
base.MouseEntered();
var drawMode = DrawMode;
_beingHovered = true;
if (drawMode != DrawMode)
{
DrawModeChanged();
}
}
protected internal override void MouseExited()
{
base.MouseExited();
var drawMode = DrawMode;
_beingHovered = false;
if (drawMode != DrawMode)
{
DrawModeChanged();
}
}
public enum DrawModeEnum
{
Normal = 0,
Pressed = 1,
Hover = 2,
Disabled = 3
}
public class ButtonEventArgs : EventArgs
{
/// <summary>
/// The button this event originated from.
/// </summary>
public BaseButton Button { get; }
public GUIBoundKeyEventArgs Event { get; }
public ButtonEventArgs(BaseButton button, GUIBoundKeyEventArgs args)
{
Button = button;
Event = args;
}
}
/// <summary>
/// Fired when a <see cref="BaseButton"/> is toggled.
/// </summary>
public class ButtonToggledEventArgs : ButtonEventArgs
{
/// <summary>
/// The new pressed state of the button.
/// </summary>
public bool Pressed { get; }
public ButtonToggledEventArgs(bool pressed, BaseButton button, GUIBoundKeyEventArgs args) : base(button, args)
{
Pressed = pressed;
}
}
/// <summary>
/// For use with <see cref="BaseButton.Mode"/>.
/// </summary>
public enum ActionMode
{
/// <summary>
/// <see cref="BaseButton.OnPressed"/> fires when the mouse button causing them is pressed down.
/// </summary>
Press = 0,
/// <summary>
/// <see cref="BaseButton.OnPressed"/> fires when the mouse button causing them is released.
/// This is the default and most intuitive method.
/// </summary>
Release = 1
}
}
}