1
0

DialogWindow.xaml.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using Content.Shared.Administration;
  2. using Robust.Client.AutoGenerated;
  3. using Robust.Client.UserInterface.Controls;
  4. using Robust.Client.UserInterface.XAML;
  5. namespace Content.Client.UserInterface.Controls;
  6. // mfw they ported input() from BYOND
  7. /// <summary>
  8. /// Client-side dialog with multiple prompts.
  9. /// Used by admin tools quick dialog system among other things.
  10. /// </summary>
  11. [GenerateTypedNameReferences]
  12. public sealed partial class DialogWindow : FancyWindow
  13. {
  14. /// <summary>
  15. /// Action for when the ok button is pressed or the last field has enter pressed.
  16. /// Results maps prompt FieldIds to the LineEdit's text contents.
  17. /// </summary>
  18. public Action<Dictionary<string, string>>? OnConfirmed;
  19. /// <summary>
  20. /// Action for when the cancel button is pressed or the window is closed.
  21. /// </summary>
  22. public Action? OnCancelled;
  23. /// <summary>
  24. /// Used to ensure that only one output action is invoked.
  25. /// E.g. Pressing cancel will invoke then close the window, but OnClose will not invoke.
  26. /// </summary>
  27. private bool _finished;
  28. private List<(string, LineEdit)> _promptLines;
  29. /// <summary>
  30. /// Create and open a new dialog with some prompts.
  31. /// </summary>
  32. /// <param name="title">String to use for the window title.</param>
  33. /// <param name="entries">Quick dialog entries to create prompts with.</param>
  34. /// <param name="ok">Whether to have an Ok button.</param>
  35. /// <param name="cancel">Whether to have a Cancel button. Closing the window will still cancel it.</param>
  36. /// <remarks>
  37. /// Won't do anything on its own, you need to handle or network with <see cref="OnConfirmed"/> and <see cref="OnCancelled"/>.
  38. /// </remarks>
  39. public DialogWindow(string title, List<QuickDialogEntry> entries, bool ok = true, bool cancel = true)
  40. {
  41. RobustXamlLoader.Load(this);
  42. Title = title;
  43. OkButton.Visible = ok;
  44. CancelButton.Visible = cancel;
  45. _promptLines = new(entries.Count);
  46. for (int i = 0; i < entries.Count; i++)
  47. {
  48. var entry = entries[i];
  49. var box = new BoxContainer();
  50. box.AddChild(new Label() { Text = entry.Prompt, HorizontalExpand = true, SizeFlagsStretchRatio = 0.5f });
  51. var edit = new LineEdit() { HorizontalExpand = true };
  52. (Func<string, bool>, string) pair = entry.Type switch
  53. {
  54. QuickDialogEntryType.Integer => (VerifyInt, "integer"),
  55. QuickDialogEntryType.Float => (VerifyFloat, "float"),
  56. QuickDialogEntryType.ShortText => (VerifyShortText, "short-text"),
  57. QuickDialogEntryType.LongText => (VerifyLongText, "long-text"),
  58. _ => throw new ArgumentOutOfRangeException()
  59. };
  60. var (valid, name) = pair;
  61. edit.IsValid += valid;
  62. // try use placeholder from the caller, fall back to the generic one for whatever type is being validated.
  63. edit.PlaceHolder = entry.Placeholder ?? Loc.GetString($"quick-dialog-ui-{name}");
  64. // Last text box gets enter confirmation.
  65. // Only the last so you don't accidentally confirm early.
  66. if (i == entries.Count - 1)
  67. edit.OnTextEntered += _ => Confirm();
  68. _promptLines.Add((entry.FieldId, edit));
  69. box.AddChild(edit);
  70. Prompts.AddChild(box);
  71. }
  72. OkButton.OnPressed += _ => Confirm();
  73. CancelButton.OnPressed += _ =>
  74. {
  75. _finished = true;
  76. OnCancelled?.Invoke();
  77. Close();
  78. };
  79. OnClose += () =>
  80. {
  81. if (!_finished)
  82. OnCancelled?.Invoke();
  83. };
  84. MinWidth *= 2; // Just double it.
  85. OpenCentered();
  86. }
  87. protected override void Opened()
  88. {
  89. base.Opened();
  90. // Grab keyboard focus for the first dialog entry
  91. _promptLines[0].Item2.GrabKeyboardFocus();
  92. }
  93. private void Confirm()
  94. {
  95. var results = new Dictionary<string, string>();
  96. foreach (var (field, edit) in _promptLines)
  97. {
  98. results[field] = edit.Text;
  99. }
  100. _finished = true;
  101. OnConfirmed?.Invoke(results);
  102. Close();
  103. }
  104. #region Input validation
  105. private bool VerifyInt(string input)
  106. {
  107. return int.TryParse(input, out var _);
  108. }
  109. private bool VerifyFloat(string input)
  110. {
  111. return float.TryParse(input, out var _);
  112. }
  113. private bool VerifyShortText(string input)
  114. {
  115. return input.Length <= 100;
  116. }
  117. private bool VerifyLongText(string input)
  118. {
  119. return input.Length <= 2000;
  120. }
  121. #endregion
  122. }