using System; using System.Collections.Generic; using Robust.Client.Graphics; using Robust.Shared.Maths; namespace Robust.Client.UserInterface.Controls { [ControlWrap("OptionButton")] public class OptionButton : Button { private List _buttonData = new List(); private Dictionary _idMap = new Dictionary(); private Popup _popup; private VBoxContainer _popupVBox; public event Action OnItemSelected; public void AddItem(Texture icon, string label, int? id = null) { AddItem(label, id); } public void AddItem(string label, int? id = null) { if (id == null) { id = _buttonData.Count; } if (_idMap.ContainsKey(id.Value)) { throw new ArgumentException("An item with the same ID already exists."); } var button = new Button { Text = label, ToggleMode = true }; button.OnPressed += ButtonOnPressed; var data = new ButtonData { Text = label, Id = id.Value, Button = button }; _idMap.Add(id.Value, _buttonData.Count); _buttonData.Add(data); _popupVBox.AddChild(button); if (_buttonData.Count == 1) { Select(0); } } private void ButtonOnPressed(ButtonEventArgs obj) { obj.Button.Pressed = false; _popup.Visible = false; foreach (var buttonData in _buttonData) { if (buttonData.Button == obj.Button) { OnItemSelected?.Invoke(new ItemSelectedEventArgs(buttonData.Id, this)); return; } } // Not reachable. throw new InvalidOperationException(); } public void Clear() { _idMap.Clear(); _buttonData.Clear(); _popupVBox.DisposeAllChildren(); SelectedId = 0; } public int ItemCount => _buttonData.Count; public int GetItemId(int idx) { return _buttonData[idx].Id; } public object GetItemMetadata(int idx) { return _buttonData[idx].Metadata; } public int SelectedId { get; private set; } public object SelectedMetadata => _buttonData[_idMap[SelectedId]].Metadata; public bool IsItemDisabled(int idx) { return _buttonData[idx].Disabled; } public void RemoveItem(int idx) { var data = _buttonData[idx]; _idMap.Remove(data.Id); _popupVBox.RemoveChild(data.Button); _buttonData.RemoveAt(idx); } public void Select(int idx) { var prev = _buttonData[_idMap[SelectedId]]; prev.Button.Pressed = false; var data = _buttonData[idx]; SelectedId = data.Id; Text = data.Text; data.Button.Pressed = true; } public void SelectId(int id) { Select(GetIdx(id)); } public int GetIdx(int id) { return _idMap[id]; } public void SetItemDisabled(int idx, bool disabled) { var data = _buttonData[idx]; data.Disabled = disabled; data.Button.Disabled = disabled; } public void SetItemIcon(int idx, Texture texture) { } public void SetItemId(int idx, int id) { if (_idMap.TryGetValue(id, out var existIdx) && existIdx != id) { throw new InvalidOperationException("An item with said ID already exists."); } var data = _buttonData[idx]; _idMap.Remove(data.Id); _idMap.Add(id, idx); data.Id = id; } public void SetItemMetadata(int idx, object metadata) { _buttonData[idx].Metadata = metadata; } public void SetItemText(int idx, string text) { var data = _buttonData[idx]; data.Text = text; if (SelectedId == data.Id) { Text = text; } data.Button.Text = text; } private void _onPressed(ButtonEventArgs args) { var globalPos = GlobalPosition; var (minX, minY) = _popupVBox.CombinedMinimumSize; var box = UIBox2.FromDimensions(globalPos, (Math.Max(minX, Width), minY)); _popup.Open(box); } public OptionButton() { } public OptionButton(string name) : base(name) { } protected override void Initialize() { base.Initialize(); OnPressed += _onPressed; _popup = new Popup(); UserInterfaceManager.ModalRoot.AddChild(_popup); _popupVBox = new VBoxContainer(); _popup.AddChild(_popupVBox); _popupVBox.SetAnchorAndMarginPreset(LayoutPreset.Wide); } protected override void Dispose(bool disposing) { base.Dispose(disposing); _popup?.Dispose(); } public class ItemSelectedEventArgs : EventArgs { public OptionButton Button { get; } /// /// The ID of the item that has been selected. /// public int Id { get; } public ItemSelectedEventArgs(int id, OptionButton button) { Id = id; Button = button; } } private sealed class ButtonData { public string Text; public bool Disabled; public object Metadata; public int Id; public Button Button; } } }