2
0

FlagSelectorTEnum.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #nullable enable
  2. namespace Terminal.Gui.Views;
  3. /// <summary>
  4. /// Provides a user interface for displaying and selecting non-mutually-exclusive flags.
  5. /// Flags can be set from a dictionary or directly from an enum type.
  6. /// </summary>
  7. public sealed class FlagSelector<TEnum> : FlagSelector where TEnum : struct, Enum
  8. {
  9. /// <summary>
  10. /// Initializes a new instance of the <see cref="FlagSelector{TEnum}"/> class.
  11. /// </summary>
  12. public FlagSelector ()
  13. {
  14. SetFlags ();
  15. }
  16. /// <summary>
  17. /// Gets or sets the value of the selected flags.
  18. /// </summary>
  19. public new TEnum? Value
  20. {
  21. get => base.Value.HasValue ? (TEnum)Enum.ToObject (typeof (TEnum), base.Value.Value) : (TEnum?)null;
  22. set => base.Value = value.HasValue ? Convert.ToUInt32 (value.Value) : (uint?)null;
  23. }
  24. /// <summary>
  25. /// Set the display names for the flags.
  26. /// </summary>
  27. /// <param name="nameSelector">A function that converts enum values to display names</param>
  28. /// <remarks>
  29. /// This method allows changing the display names of the flags while keeping the flag values hard-defined by the enum type.
  30. /// </remarks>
  31. /// <example>
  32. /// <code>
  33. /// // Use enum values with custom display names
  34. /// var flagSelector = new FlagSelector&lt;FlagSelectorStyles&gt;();
  35. /// flagSelector.SetFlagNames(f => f switch {
  36. /// FlagSelectorStyles.ShowNone => "Show None Value",
  37. /// FlagSelectorStyles.ShowValueEdit => "Show Value Editor",
  38. /// FlagSelectorStyles.All => "Everything",
  39. /// _ => f.ToString()
  40. /// });
  41. /// </code>
  42. /// </example>
  43. public void SetFlagNames (Func<TEnum, string> nameSelector)
  44. {
  45. Dictionary<uint, string> flagsDictionary = Enum.GetValues<TEnum> ()
  46. .ToDictionary (f => Convert.ToUInt32 (f), nameSelector);
  47. base.SetFlags (flagsDictionary);
  48. }
  49. private void SetFlags ()
  50. {
  51. Dictionary<uint, string> flagsDictionary = Enum.GetValues<TEnum> ()
  52. .ToDictionary (f => Convert.ToUInt32 (f), f => f.ToString ());
  53. base.SetFlags (flagsDictionary);
  54. }
  55. /// <summary>
  56. /// Prevents calling the base SetFlags method with arbitrary flag values.
  57. /// </summary>
  58. /// <param name="flags"></param>
  59. public override void SetFlags (IReadOnlyDictionary<uint, string> flags)
  60. {
  61. throw new InvalidOperationException ("Setting flag values directly is not allowed. Use SetFlagNames to change display names.");
  62. }
  63. /// <inheritdoc />
  64. protected override CheckBox CreateCheckBox (string name, uint flag)
  65. {
  66. var checkbox = base.CreateCheckBox (name, flag);
  67. checkbox.CheckedStateChanged += (sender, args) =>
  68. {
  69. TEnum? newValue = Value;
  70. if (checkbox.CheckedState == CheckState.Checked)
  71. {
  72. if (flag == default!)
  73. {
  74. newValue = new TEnum ();
  75. }
  76. else
  77. {
  78. newValue = (TEnum)Enum.ToObject (typeof (TEnum), Convert.ToUInt32 (newValue) | flag);
  79. }
  80. }
  81. else
  82. {
  83. newValue = (TEnum)Enum.ToObject (typeof (TEnum), Convert.ToUInt32 (newValue) & ~flag);
  84. }
  85. Value = newValue;
  86. };
  87. return checkbox;
  88. }
  89. }