RadioGroup.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 (s.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>
  37. /// <summary>
  38. public RadioGroup (int x, int y, string [] radioLabels, int selected = 0) : this (MakeRect (x, y, radioLabels), radioLabels, selected)
  39. {
  40. }
  41. string [] radioLabels;
  42. /// <summary>
  43. /// The radio labels to display
  44. /// </summary>
  45. /// <value>The radio labels.</value>
  46. public string [] RadioLabels {
  47. get => radioLabels;
  48. set {
  49. radioLabels = value;
  50. selected = 0;
  51. cursor = 0;
  52. SetNeedsDisplay ();
  53. }
  54. }
  55. public override void Redraw (Rect region)
  56. {
  57. base.Redraw (region);
  58. for (int i = 0; i < radioLabels.Length; i++) {
  59. Move (0, i);
  60. Driver.SetAttribute (Colors.Base.Normal);
  61. Driver.AddStr (i == selected ? "(o) " : "( ) ");
  62. DrawHotString (radioLabels [i], HasFocus && i == cursor, Colors.Base);
  63. }
  64. }
  65. public override void PositionCursor ()
  66. {
  67. Move (1, cursor);
  68. }
  69. public Action<int> SelectionChanged;
  70. /// <summary>
  71. /// The currently selected item from the list of radio labels
  72. /// </summary>
  73. /// <value>The selected.</value>
  74. public int Selected {
  75. get => selected;
  76. set {
  77. selected = value;
  78. SelectionChanged?.Invoke (selected);
  79. SetNeedsDisplay ();
  80. }
  81. }
  82. public override bool ProcessHotKey (KeyEvent kb)
  83. {
  84. var key = kb.KeyValue;
  85. if (key < Char.MaxValue && Char.IsLetterOrDigit ((char)key)) {
  86. int i = 0;
  87. key = Char.ToUpper ((char)key);
  88. foreach (var l in radioLabels) {
  89. bool nextIsHot = false;
  90. foreach (var c in l) {
  91. if (c == '_')
  92. nextIsHot = true;
  93. else {
  94. if (nextIsHot && c == key) {
  95. Selected = i;
  96. cursor = i;
  97. if (!HasFocus)
  98. SuperView.SetFocus (this);
  99. return true;
  100. }
  101. nextIsHot = false;
  102. }
  103. }
  104. i++;
  105. }
  106. }
  107. return false;
  108. }
  109. public override bool ProcessKey (KeyEvent kb)
  110. {
  111. switch (kb.Key) {
  112. case Key.CursorUp:
  113. if (cursor > 0) {
  114. cursor--;
  115. SetNeedsDisplay ();
  116. }
  117. return true;
  118. case Key.CursorDown:
  119. if (cursor + 1 < radioLabels.Length) {
  120. cursor++;
  121. SetNeedsDisplay ();
  122. }
  123. return true;
  124. case Key.Space:
  125. Selected = cursor;
  126. return true;
  127. }
  128. return base.ProcessKey (kb);
  129. }
  130. public override bool MouseEvent (MouseEvent me)
  131. {
  132. if (!me.Flags.HasFlag (MouseFlags.Button1Clicked))
  133. return false;
  134. SuperView.SetFocus (this);
  135. if (me.Y < radioLabels.Length) {
  136. cursor = selected = me.Y;
  137. SetNeedsDisplay ();
  138. }
  139. return true;
  140. }
  141. }
  142. }