|
@@ -0,0 +1,143 @@
|
|
|
|
+using System;
|
|
|
|
+namespace Terminal {
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Radio group shows a group of labels, only one of those can be selected at a given time
|
|
|
|
+ /// </summary>
|
|
|
|
+ public class RadioGroup : View {
|
|
|
|
+ int selected, cursor;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Initializes a new instance of the <see cref="T:Terminal.RadioGroup"/> class
|
|
|
|
+ /// setting up the initial set of radio labels and the item that should be selected.
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="rect">Boundaries for the radio group.</param>
|
|
|
|
+ /// <param name="radioLabels">Radio labels, the strings can contain hotkeys using an undermine before the letter.</param>
|
|
|
|
+ /// <param name="selected">The item to be selected, the value is clamped to the number of items.</param>
|
|
|
|
+ public RadioGroup (Rect rect, string [] radioLabels, int selected = 0) : base (rect)
|
|
|
|
+ {
|
|
|
|
+ this.selected = selected;
|
|
|
|
+ this.radioLabels = radioLabels;
|
|
|
|
+ CanFocus = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static Rect MakeRect (int x, int y, string [] radioLabels)
|
|
|
|
+ {
|
|
|
|
+ int width = 0;
|
|
|
|
+
|
|
|
|
+ foreach (var s in radioLabels)
|
|
|
|
+ width = Math.Max (radioLabels.Length + 4, width);
|
|
|
|
+ return new Rect (x, y, width, radioLabels.Length);
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Initializes a new instance of the <see cref="T:Terminal.RadioGroup"/> class
|
|
|
|
+ /// setting up the initial set of radio labels and the item that should be selected,
|
|
|
|
+ /// the view frame is computed from the provided radioLabels.
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="x">The x coordinate.</param>
|
|
|
|
+ /// <param name="y">The y coordinate.</param>
|
|
|
|
+ /// <param name="radioLabels">Radio labels, the strings can contain hotkeys using an undermine before the letter.</param>
|
|
|
|
+ /// <param name="selected">The item to be selected, the value is clamped to the number of items.</param> /// <summary>
|
|
|
|
+ public RadioGroup (int x, int y, string [] radioLabels, int selected = 0) : this (MakeRect (x, y, radioLabels), radioLabels, selected)
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ string [] radioLabels;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// The radio labels to display
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <value>The radio labels.</value>
|
|
|
|
+ public string [] RadioLabels {
|
|
|
|
+ get => radioLabels;
|
|
|
|
+ set {
|
|
|
|
+ radioLabels = value;
|
|
|
|
+ selected = 0;
|
|
|
|
+ cursor = 0;
|
|
|
|
+ SetNeedsDisplay ();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override void Redraw (Rect region)
|
|
|
|
+ {
|
|
|
|
+ base.Redraw (region);
|
|
|
|
+ for (int i = 0; i < radioLabels.Length; i++) {
|
|
|
|
+ Move (0, i);
|
|
|
|
+ Driver.SetAttribute (Colors.Base.Normal);
|
|
|
|
+ Driver.AddStr (i == selected ? "(o) " : "( ) ");
|
|
|
|
+ DrawHotString (radioLabels [i], HasFocus && i == cursor, Colors.Base);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override void PositionCursor ()
|
|
|
|
+ {
|
|
|
|
+ Move (1, cursor);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public Action<int> SelectionChanged;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// The currently selected item from the list of radio labels
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <value>The selected.</value>
|
|
|
|
+ public int Selected {
|
|
|
|
+ get => selected;
|
|
|
|
+ set {
|
|
|
|
+ selected = value;
|
|
|
|
+ SelectionChanged?.Invoke (selected);
|
|
|
|
+ SetNeedsDisplay ();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override bool ProcessHotKey (KeyEvent kb)
|
|
|
|
+ {
|
|
|
|
+ var key = kb.KeyValue;
|
|
|
|
+ if (key < Char.MaxValue && Char.IsLetterOrDigit ((char)key)) {
|
|
|
|
+ int i = 0;
|
|
|
|
+ key = Char.ToUpper ((char)key);
|
|
|
|
+ foreach (var l in radioLabels) {
|
|
|
|
+ bool nextIsHot = false;
|
|
|
|
+ foreach (var c in l) {
|
|
|
|
+ if (c == '_')
|
|
|
|
+ nextIsHot = true;
|
|
|
|
+ else {
|
|
|
|
+ if (nextIsHot && c == key) {
|
|
|
|
+ Selected = i;
|
|
|
|
+ cursor = i;
|
|
|
|
+ if (!HasFocus)
|
|
|
|
+ SuperView.SetFocus (this);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ nextIsHot = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ i++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override bool ProcessKey (KeyEvent kb)
|
|
|
|
+ {
|
|
|
|
+ switch (kb.Key) {
|
|
|
|
+ case Key.CursorUp:
|
|
|
|
+ if (cursor > 0) {
|
|
|
|
+ cursor--;
|
|
|
|
+ SetNeedsDisplay ();
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ case Key.CursorDown:
|
|
|
|
+ if (cursor + 1 < radioLabels.Length) {
|
|
|
|
+ cursor++;
|
|
|
|
+ SetNeedsDisplay ();
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ case Key.Space:
|
|
|
|
+ Selected = cursor;
|
|
|
|
+ return true;
|
|
|
|
+ default:
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|