mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
* 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
255 lines
7.0 KiB
C#
255 lines
7.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Robust.Shared.Maths;
|
|
|
|
namespace Robust.Client.UserInterface.Controls
|
|
{
|
|
/// <summary>
|
|
/// A good simple menu bar control, like the one at the top of your IDE!
|
|
/// </summary>
|
|
public class MenuBar : PanelContainer
|
|
{
|
|
private readonly List<Menu> _menus = new List<Menu>();
|
|
private readonly List<MenuBarTopButton> _buttons = new List<MenuBarTopButton>();
|
|
private readonly HBoxContainer _hBox;
|
|
private readonly Popup _popup;
|
|
private readonly VBoxContainer _popupVBox;
|
|
private bool _popupOpen;
|
|
|
|
public IList<Menu> Menus { get; }
|
|
|
|
public MenuBar()
|
|
{
|
|
_popup = new Popup
|
|
{
|
|
Children =
|
|
{
|
|
(_popupVBox = new VBoxContainer {CustomMinimumSize = (300, 0)})
|
|
}
|
|
};
|
|
_popup.OnPopupHide += PopupHidden;
|
|
UserInterfaceManager.ModalRoot.AddChild(_popup);
|
|
Menus = new MenuCollection(this);
|
|
AddChild(_hBox = new HBoxContainer {SeparationOverride = 8});
|
|
}
|
|
|
|
private void AddMenu(Menu menu)
|
|
{
|
|
var button = new MenuBarTopButton(menu);
|
|
_menus.Add(menu);
|
|
_buttons.Add(button);
|
|
_hBox.AddChild(button);
|
|
|
|
button.OnKeyBindDown += _ => OpenPopupFor(button);
|
|
|
|
button.OnMouseEntered += () =>
|
|
{
|
|
if (_popupOpen)
|
|
{
|
|
OpenPopupFor(button);
|
|
}
|
|
};
|
|
}
|
|
|
|
private void OpenPopupFor(MenuBarTopButton button)
|
|
{
|
|
_popupVBox.RemoveAllChildren();
|
|
var menu = button.Menu;
|
|
ConstructMenu(menu, _popupVBox);
|
|
|
|
var globalPos = button.GlobalPosition;
|
|
globalPos += (0, button.Height);
|
|
_popup.Open(UIBox2.FromDimensions(globalPos, _popupVBox.Size));
|
|
|
|
// Set this after running open so that if this is called from MouseEntered,
|
|
// It won't get set to false by Open() closing the popup to move it.
|
|
_popupOpen = true;
|
|
}
|
|
|
|
private void PopupHidden()
|
|
{
|
|
_popupOpen = false;
|
|
}
|
|
|
|
private bool RemoveMenu(Menu menu)
|
|
{
|
|
var index = _menus.IndexOf(menu);
|
|
if (index < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var button = _buttons[index];
|
|
|
|
_hBox.RemoveChild(button);
|
|
_buttons.RemoveAt(index);
|
|
_menus.RemoveAt(index);
|
|
|
|
return false;
|
|
}
|
|
|
|
private void ConstructMenu(Menu menu, Control container)
|
|
{
|
|
foreach (var entry in menu.Entries)
|
|
{
|
|
switch (entry)
|
|
{
|
|
case MenuButton menuButton:
|
|
var pushButton = new Button
|
|
{
|
|
Text = menuButton.Text,
|
|
ClipText = true,
|
|
Disabled = menuButton.Disabled,
|
|
TextAlign = Button.AlignMode.Left
|
|
};
|
|
pushButton.OnPressed += _ => menuButton.OnPressed?.Invoke();
|
|
container.AddChild(pushButton);
|
|
break;
|
|
|
|
case MenuSeparator _:
|
|
var control = new Control {CustomMinimumSize = (0, 6)};
|
|
container.AddChild(control);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed class MenuCollection : IList<Menu>
|
|
{
|
|
private readonly MenuBar _menuBar;
|
|
|
|
public MenuCollection(MenuBar menuBar)
|
|
{
|
|
_menuBar = menuBar;
|
|
}
|
|
|
|
public IEnumerator<Menu> GetEnumerator()
|
|
{
|
|
return _menuBar._menus.GetEnumerator();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
|
|
public void Add(Menu item)
|
|
{
|
|
_menuBar.AddMenu(item);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
foreach (var menu in this.ToList())
|
|
{
|
|
Remove(menu);
|
|
}
|
|
}
|
|
|
|
public bool Contains(Menu item)
|
|
{
|
|
return _menuBar._menus.Contains(item);
|
|
}
|
|
|
|
public void CopyTo(Menu[] array, int arrayIndex)
|
|
{
|
|
_menuBar._menus.CopyTo(array, arrayIndex);
|
|
}
|
|
|
|
public bool Remove(Menu item)
|
|
{
|
|
return _menuBar.RemoveMenu(item);
|
|
}
|
|
|
|
public int Count => _menuBar._menus.Count;
|
|
public bool IsReadOnly => false;
|
|
|
|
public int IndexOf(Menu item)
|
|
{
|
|
return _menuBar._menus.IndexOf(item);
|
|
}
|
|
|
|
public void Insert(int index, Menu item)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void RemoveAt(int index)
|
|
{
|
|
Remove(this[index]);
|
|
}
|
|
|
|
public Menu this[int index]
|
|
{
|
|
get => _menuBar._menus[index];
|
|
set => throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
public sealed class MenuBarTopButton : PanelContainer
|
|
{
|
|
public const string StylePseudoClassHover = "hover";
|
|
|
|
public Label Label { get; }
|
|
public Menu Menu { get; }
|
|
|
|
public event Action OnMouseEntered;
|
|
|
|
public MenuBarTopButton(Menu menu)
|
|
{
|
|
Menu = menu;
|
|
AddChild(Label = new Label {Text = menu.Title});
|
|
}
|
|
|
|
protected internal override void MouseEntered()
|
|
{
|
|
base.MouseEntered();
|
|
|
|
OnMouseEntered?.Invoke();
|
|
|
|
SetOnlyStylePseudoClass(StylePseudoClassHover);
|
|
}
|
|
|
|
protected internal override void MouseExited()
|
|
{
|
|
base.MouseExited();
|
|
|
|
SetOnlyStylePseudoClass(null);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// An entry in a menu of a menu bar.
|
|
/// </summary>
|
|
public abstract class MenuEntry
|
|
{
|
|
private protected MenuEntry()
|
|
{
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A menu in a menu bar, like file...
|
|
/// </summary>
|
|
public sealed class Menu
|
|
{
|
|
public string Title { get; set; }
|
|
|
|
public List<MenuEntry> Entries { get; } = new List<MenuEntry>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// A basic button entry in a menu bar menu.
|
|
/// </summary>
|
|
public sealed class MenuButton : MenuEntry
|
|
{
|
|
public string Text { get; set; }
|
|
public bool Disabled { get; set; }
|
|
public Action OnPressed { get; set; }
|
|
}
|
|
|
|
public sealed class MenuSeparator : MenuEntry
|
|
{
|
|
}
|
|
}
|
|
}
|