ChatPopupButton.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using Robust.Client.UserInterface;
  2. using Robust.Client.UserInterface.Controls;
  3. using Robust.Shared.Timing;
  4. namespace Content.Client.UserInterface.Systems.Chat.Controls;
  5. // NO MORE FUCKING COPY PASTING THIS SHIT
  6. /// <summary>
  7. /// Base class for button that toggles a popup-window.
  8. /// Base type of <see cref="ChannelFilterButton"/> and <see cref="ChannelSelectorButton"/>.
  9. /// </summary>
  10. public abstract class ChatPopupButton<TPopup> : Button
  11. where TPopup : Popup, new()
  12. {
  13. private readonly IGameTiming _gameTiming;
  14. public readonly TPopup Popup;
  15. private uint _frameLastPopupChanged;
  16. protected ChatPopupButton()
  17. {
  18. _gameTiming = IoCManager.Resolve<IGameTiming>();
  19. ToggleMode = true;
  20. OnToggled += OnButtonToggled;
  21. Popup = UserInterfaceManager.CreatePopup<TPopup>();
  22. Popup.OnVisibilityChanged += OnPopupVisibilityChanged;
  23. }
  24. protected override void KeyBindDown(GUIBoundKeyEventArgs args)
  25. {
  26. // If you try to close the popup by clicking on the button again the following would happen:
  27. // The UI system would see that you clicked outside a popup, and would close it.
  28. // Because of the above logic, that sets the button to UNPRESSED.
  29. // THEN, it would propagate the keyboard event to us, the chat selector...
  30. // And we would become pressed again.
  31. // As a workaround, we check the frame the popup was last dismissed (above)
  32. // and don't allow changing it again this frame.
  33. if (_frameLastPopupChanged == _gameTiming.CurFrame)
  34. return;
  35. base.KeyBindDown(args);
  36. }
  37. protected abstract UIBox2 GetPopupPosition();
  38. private void OnButtonToggled(ButtonToggledEventArgs args)
  39. {
  40. if (args.Pressed)
  41. {
  42. Popup.Open(GetPopupPosition());
  43. }
  44. else
  45. {
  46. Popup.Close();
  47. }
  48. }
  49. private void OnPopupVisibilityChanged(Control control)
  50. {
  51. // If the popup gets closed (e.g. by clicking anywhere else on the screen)
  52. // We clear the button pressed state.
  53. Pressed = control.Visible;
  54. _frameLastPopupChanged = _gameTiming.CurFrame;
  55. }
  56. }