RadioButton

This commit is contained in:
Miguel de Icaza
2018-01-07 14:40:20 -05:00
parent c763c808e3
commit 305bfaf135
5 changed files with 181 additions and 3 deletions

16
Core.cs
View File

@@ -343,7 +343,7 @@ namespace Terminal {
/// <summary>
/// Utility function to draw strings that contain a hotkey
/// </summary>
/// <param name="s">String to display, the underscoore before a letter flags the next letter as the hotkey.</param>
/// <param name="text">String to display, the underscoore before a letter flags the next letter as the hotkey.</param>
/// <param name="hotColor">Hot color.</param>
/// <param name="normalColor">Normal color.</param>
public void DrawHotString (string text, Attribute hotColor, Attribute normalColor)
@@ -359,6 +359,20 @@ namespace Terminal {
}
}
/// <summary>
/// Utility function to draw strings that contains a hotkey using a colorscheme and the "focused" state.
/// </summary>
/// <param name="text">String to display, the underscoore before a letter flags the next letter as the hotkey.</param>
/// <param name="focused">If set to <c>true</c> this uses the focused colors from the color scheme, otherwise the regular ones.</param>
/// <param name="scheme">The color scheme to use.</param>
public void DrawHotString (string text, bool focused, ColorScheme scheme)
{
if (focused)
DrawHotString (text, scheme.HotFocus, scheme.Focus);
else
DrawHotString (text, scheme.HotNormal, scheme.Normal);
}
/// <summary>
/// This moves the cursor to the specified column and row in the view.
/// </summary>

19
TODO.md
View File

@@ -29,11 +29,17 @@ Should include another theme, like the TurboPascal 6 theme
Replaces `Colors.Base.Normal` with `Attributes.Normal`, and perhaps attributes
points to the container.
Widgets should not use Colors.Base or Colors.Dialog, they should likely use
the colors defined in the toplevel container, so that the Dialog vs Toplevel
colors are set there only.
## Views
Checkbox, ListView, Menu.
Wanted:
- HotLabels (should be labelsw ith a hotkey that take a focus view as an argument)
- MessageBox
- Function Bar
- ScrollView
- Multi-line text editing
@@ -43,6 +49,11 @@ Wanted:
- Submenus in menus.
- Popup menus
- Make windows draggable
- ListView
- TreeView
- View + Attribute for SolidFills?
- Scrollbar
- Frame container (with label)
High-level widgets:
- Time selector
@@ -50,10 +61,18 @@ High-level widgets:
- File selector
- Masked input
Graphs:
- Progress bar
Should Views support Padding/Margin/Border? Would make it simpler for Forms backend and perhaps
adopt the Forms CSS as-is
## Layout manager
Unclear what to do about that right now. Perhaps use Flex?
Will at least need the protocol for sizing
# Unicode
Needs to move to `ustring` from `NStack.Core` to get full Unicode support.

View File

@@ -46,6 +46,7 @@
<Compile Include="Views\Menu.cs" />
<Compile Include="Views\ScrollView.cs" />
<Compile Include="Views\Dialog.cs" />
<Compile Include="Views\RadioGroup.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mono-curses.dll">

143
Views/RadioGroup.cs Normal file
View File

@@ -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;
}
}
}
}

View File

@@ -18,8 +18,9 @@ class Demo {
new Label (3, 4, "Password: "),
new TextField (14, 4, 40, "") { Secret = true },
new CheckBox (3, 6, "Remember me"),
new Button (3, 8, "Ok"),
new Button (10, 8, "Cancel"),
new RadioGroup (3, 8, new [] { "_Personal", "_Company" }),
new Button (3, 14, "Ok"),
new Button (10, 14, "Cancel"),
new Label (3, 18, "Press ESC and 9 to activate the menubar")
);
}