RadioGroup.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using System;
  2. namespace Terminal {
  3. /// <summary>
  4. /// Radio group shows a group of labels, only one of those can be selected at a given time
  5. /// </summary>
  6. public class RadioGroup : View {
  7. int selected, cursor;
  8. /// <summary>
  9. /// Initializes a new instance of the <see cref="T:Terminal.RadioGroup"/> class
  10. /// setting up the initial set of radio labels and the item that should be selected.
  11. /// </summary>
  12. /// <param name="rect">Boundaries for the radio group.</param>
  13. /// <param name="radioLabels">Radio labels, the strings can contain hotkeys using an undermine before the letter.</param>
  14. /// <param name="selected">The item to be selected, the value is clamped to the number of items.</param>
  15. public RadioGroup (Rect rect, string [] radioLabels, int selected = 0) : base (rect)
  16. {
  17. this.selected = selected;
  18. this.radioLabels = radioLabels;
  19. CanFocus = true;
  20. }
  21. static Rect MakeRect (int x, int y, string [] radioLabels)
  22. {
  23. int width = 0;
  24. foreach (var s in radioLabels)
  25. width = Math.Max (radioLabels.Length + 4, width);
  26. return new Rect (x, y, width, radioLabels.Length);
  27. }
  28. /// <summary>
  29. /// Initializes a new instance of the <see cref="T:Terminal.RadioGroup"/> class
  30. /// setting up the initial set of radio labels and the item that should be selected,
  31. /// the view frame is computed from the provided radioLabels.
  32. /// </summary>
  33. /// <param name="x">The x coordinate.</param>
  34. /// <param name="y">The y coordinate.</param>
  35. /// <param name="radioLabels">Radio labels, the strings can contain hotkeys using an undermine before the letter.</param>
  36. /// <param name="selected">The item to be selected, the value is clamped to the number of items.</param> /// <summary>
  37. public RadioGroup (int x, int y, string [] radioLabels, int selected = 0) : this (MakeRect (x, y, radioLabels), radioLabels, selected)
  38. {
  39. }
  40. string [] radioLabels;
  41. /// <summary>
  42. /// The radio labels to display
  43. /// </summary>
  44. /// <value>The radio labels.</value>
  45. public string [] RadioLabels {
  46. get => radioLabels;
  47. set {
  48. radioLabels = value;
  49. selected = 0;
  50. cursor = 0;
  51. SetNeedsDisplay ();
  52. }
  53. }
  54. public override void Redraw (Rect region)
  55. {
  56. base.Redraw (region);
  57. for (int i = 0; i < radioLabels.Length; i++) {
  58. Move (0, i);
  59. Driver.SetAttribute (Colors.Base.Normal);
  60. Driver.AddStr (i == selected ? "(o) " : "( ) ");
  61. DrawHotString (radioLabels [i], HasFocus && i == cursor, Colors.Base);
  62. }
  63. }
  64. public override void PositionCursor ()
  65. {
  66. Move (1, cursor);
  67. }
  68. public Action<int> SelectionChanged;
  69. /// <summary>
  70. /// The currently selected item from the list of radio labels
  71. /// </summary>
  72. /// <value>The selected.</value>
  73. public int Selected {
  74. get => selected;
  75. set {
  76. selected = value;
  77. SelectionChanged?.Invoke (selected);
  78. SetNeedsDisplay ();
  79. }
  80. }
  81. public override bool ProcessHotKey (KeyEvent kb)
  82. {
  83. var key = kb.KeyValue;
  84. if (key < Char.MaxValue && Char.IsLetterOrDigit ((char)key)) {
  85. int i = 0;
  86. key = Char.ToUpper ((char)key);
  87. foreach (var l in radioLabels) {
  88. bool nextIsHot = false;
  89. foreach (var c in l) {
  90. if (c == '_')
  91. nextIsHot = true;
  92. else {
  93. if (nextIsHot && c == key) {
  94. Selected = i;
  95. cursor = i;
  96. if (!HasFocus)
  97. SuperView.SetFocus (this);
  98. return true;
  99. }
  100. nextIsHot = false;
  101. }
  102. }
  103. i++;
  104. }
  105. }
  106. return false;
  107. }
  108. public override bool ProcessKey (KeyEvent kb)
  109. {
  110. switch (kb.Key) {
  111. case Key.CursorUp:
  112. if (cursor > 0) {
  113. cursor--;
  114. SetNeedsDisplay ();
  115. }
  116. return true;
  117. case Key.CursorDown:
  118. if (cursor + 1 < radioLabels.Length) {
  119. cursor++;
  120. SetNeedsDisplay ();
  121. }
  122. return true;
  123. case Key.Space:
  124. Selected = cursor;
  125. return true;
  126. }
  127. return base.ProcessKey (kb);
  128. }
  129. public override bool MouseEvent (MouseEvent me)
  130. {
  131. if (!me.Flags.HasFlag (MouseFlags.Button1Clicked))
  132. return false;
  133. SuperView.SetFocus (this);
  134. if (me.Y < radioLabels.Length) {
  135. cursor = selected = me.Y;
  136. SetNeedsDisplay ();
  137. }
  138. return true;
  139. }
  140. }
  141. }