diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 501dceed7..650e333a5 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -186,12 +186,12 @@ namespace Terminal.Gui {
///
/// Gets or sets the HotKey defined for this view. A user pressing HotKey on the keyboard while this view has focus will cause the Clicked event to fire.
///
- public Key HotKey { get => textFormatter.HotKey; set => textFormatter.HotKey = value; }
+ public virtual Key HotKey { get => textFormatter.HotKey; set => textFormatter.HotKey = value; }
///
/// Gets or sets the specifier character for the hotkey (e.g. '_'). Set to '\xffff' to disable hotkey support for this View instance. The default is '\xffff'.
///
- public Rune HotKeySpecifier { get => textFormatter.HotKeySpecifier; set => textFormatter.HotKeySpecifier = value; }
+ public virtual Rune HotKeySpecifier { get => textFormatter.HotKeySpecifier; set => textFormatter.HotKeySpecifier = value; }
///
/// This is the global setting that can be used as a global shortcut to invoke an action if provided.
diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs
index ae50617a8..e48f4bdef 100644
--- a/Terminal.Gui/Views/Button.cs
+++ b/Terminal.Gui/Views/Button.cs
@@ -33,6 +33,7 @@ namespace Terminal.Gui {
public class Button : View {
ustring text;
bool is_default;
+ TextFormatter textFormatter = new TextFormatter ();
///
/// Initializes a new instance of using layout.
@@ -96,6 +97,8 @@ namespace Terminal.Gui {
Rune _rightBracket;
Rune _leftDefault;
Rune _rightDefault;
+ private Key hotKey = Key.Null;
+ private Rune hotKeySpecifier;
void Initialize (ustring text, bool is_default)
{
@@ -113,8 +116,6 @@ namespace Terminal.Gui {
this.text = text ?? string.Empty;
Update ();
- HotKeyChanged += Button_HotKeyChanged;
-
// Things this view knows how to do
AddCommand (Command.Accept, () => AcceptKey ());
@@ -126,27 +127,17 @@ namespace Terminal.Gui {
}
}
- private void Button_HotKeyChanged (Key obj)
- {
- if (HotKey != Key.Null) {
- if (ContainsKeyBinding (obj)) {
- ReplaceKeyBinding (Key.Space | obj, Key.Space | HotKey);
- } else {
- AddKeyBinding (Key.Space | HotKey, Command.Accept);
- }
- }
- }
-
- ///
- /// The text displayed by this .
- ///
- public new ustring Text {
+ /// >
+ public override ustring Text {
get {
return text;
}
-
set {
text = value;
+ TextFormatter.FindHotKey (text, HotKeySpecifier, true, out _, out Key hk);
+ if (hotKey != hk) {
+ HotKey = hk;
+ }
Update ();
}
}
@@ -163,14 +154,51 @@ namespace Terminal.Gui {
}
}
+ ///
+ public override Key HotKey {
+ get => hotKey;
+ set {
+ if (hotKey != value) {
+ var v = value == Key.Unknown ? Key.Null : value;
+ if (ContainsKeyBinding (Key.Space | hotKey)) {
+ if (v == Key.Null) {
+ ClearKeybinding (Key.Space | hotKey);
+ } else {
+ ReplaceKeyBinding (Key.Space | hotKey, Key.Space | v);
+ }
+ } else if (v != Key.Null) {
+ AddKeyBinding (Key.Space | v, Command.Accept);
+ }
+ hotKey = v;
+ }
+ }
+ }
+
+ ///
+ public override Rune HotKeySpecifier {
+ get => hotKeySpecifier;
+ set {
+ hotKeySpecifier = textFormatter.HotKeySpecifier = value;
+ }
+ }
+
+ ///
+ public override bool AutoSize {
+ get => base.AutoSize;
+ set {
+ base.AutoSize = value;
+ Update ();
+ }
+ }
+
internal void Update ()
{
if (IsDefault)
- base.Text = ustring.Make (_leftBracket) + ustring.Make (_leftDefault) + " " + text + " " + ustring.Make (_rightDefault) + ustring.Make (_rightBracket);
+ textFormatter.Text = ustring.Make (_leftBracket) + ustring.Make (_leftDefault) + " " + text + " " + ustring.Make (_rightDefault) + ustring.Make (_rightBracket);
else
- base.Text = ustring.Make (_leftBracket) + " " + text + " " + ustring.Make (_rightBracket);
+ textFormatter.Text = ustring.Make (_leftBracket) + " " + text + " " + ustring.Make (_rightBracket);
- int w = base.Text.RuneCount - (base.Text.Contains (HotKeySpecifier) ? 1 : 0);
+ int w = textFormatter.Text.RuneCount - (textFormatter.Text.Contains (HotKeySpecifier) ? 1 : 0);
GetCurrentWidth (out int cWidth);
var canSetWidth = SetWidth (w, out int rWidth);
if (canSetWidth && (cWidth < rWidth || AutoSize)) {
@@ -194,6 +222,25 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
}
+ ///
+ public override void Redraw (Rect bounds)
+ {
+ if (ColorScheme != null) {
+ Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
+ }
+
+ if (Border != null) {
+ Border.DrawContent (this);
+ }
+
+ if (!ustring.IsNullOrEmpty (textFormatter.Text)) {
+ Clear ();
+ textFormatter.NeedsFormat = true;
+ textFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? ColorScheme.Focus : GetNormalColor (),
+ HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled);
+ }
+ }
+
///
public override bool ProcessHotKey (KeyEvent kb)
{
@@ -294,8 +341,8 @@ namespace Terminal.Gui {
public override void PositionCursor ()
{
if (HotKey == Key.Unknown && text != "") {
- for (int i = 0; i < base.Text.RuneCount; i++) {
- if (base.Text [i] == text [0]) {
+ for (int i = 0; i < textFormatter.Text.RuneCount; i++) {
+ if (textFormatter.Text [i] == text [0]) {
Move (i, 0);
return;
}
diff --git a/UnitTests/ButtonTests.cs b/UnitTests/ButtonTests.cs
index 74936741a..153e7ef33 100644
--- a/UnitTests/ButtonTests.cs
+++ b/UnitTests/ButtonTests.cs
@@ -7,12 +7,14 @@ using Xunit;
namespace Terminal.Gui.Views {
public class ButtonTests {
- [Fact]
+ [Fact, AutoInitShutdown]
public void Constructors_Defaults ()
{
var btn = new Button ();
Assert.Equal (string.Empty, btn.Text);
- Assert.Equal ("[ ]", btn.GetType ().BaseType.GetProperty ("Text").GetValue (btn).ToString ());
+ Application.Top.Add (btn);
+ btn.Redraw (btn.Bounds);
+ Assert.Equal ("[ ]", GetContents (btn.Bounds.Width));
Assert.False (btn.IsDefault);
Assert.Equal (TextAlignment.Centered, btn.TextAlignment);
Assert.Equal ('_', btn.HotKeySpecifier);
@@ -22,23 +24,36 @@ namespace Terminal.Gui.Views {
btn = new Button ("Test", true);
Assert.Equal ("Test", btn.Text);
- Assert.Equal ("[< Test >]", btn.GetType ().BaseType.GetProperty ("Text").GetValue (btn).ToString ());
+ Application.Top.Add (btn);
+ btn.Redraw (btn.Bounds);
+ Assert.Equal ("[◦ Test ◦]", GetContents (btn.Bounds.Width));
Assert.True (btn.IsDefault);
Assert.Equal (TextAlignment.Centered, btn.TextAlignment);
Assert.Equal ('_', btn.HotKeySpecifier);
Assert.True (btn.CanFocus);
Assert.Equal (new Rect (0, 0, 10, 1), btn.Frame);
- Assert.Equal (Key.Null, btn.HotKey);
+ Assert.Equal (Key.T, btn.HotKey);
btn = new Button (3, 4, "Test", true);
Assert.Equal ("Test", btn.Text);
- Assert.Equal ("[< Test >]", btn.GetType ().BaseType.GetProperty ("Text").GetValue (btn).ToString ());
+ Application.Top.Add (btn);
+ btn.Redraw (btn.Bounds);
+ Assert.Equal ("[◦ Test ◦]", GetContents (btn.Bounds.Width));
Assert.True (btn.IsDefault);
Assert.Equal (TextAlignment.Centered, btn.TextAlignment);
Assert.Equal ('_', btn.HotKeySpecifier);
Assert.True (btn.CanFocus);
Assert.Equal (new Rect (3, 4, 10, 1), btn.Frame);
- Assert.Equal (Key.Null, btn.HotKey);
+ Assert.Equal (Key.T, btn.HotKey);
+ }
+
+ private string GetContents (int width)
+ {
+ string output = "";
+ for (int i = 0; i < width; i++) {
+ output += (char)Application.Driver.Contents [0, i, 0];
+ }
+ return output;
}
[Fact]
@@ -75,9 +90,15 @@ namespace Terminal.Gui.Views {
clicked = false;
Assert.True (btn.ProcessKey (new KeyEvent ((Key)'t', new KeyModifiers ())));
Assert.True (clicked);
+ clicked = false;
+ Assert.True (btn.ProcessKey (new KeyEvent (Key.Space | btn.HotKey, new KeyModifiers ())));
+ Assert.True (clicked);
+ btn.Text = "Te_st";
+ clicked = false;
+ Assert.True (btn.ProcessKey (new KeyEvent (Key.Space | btn.HotKey, new KeyModifiers ())));
+ Assert.True (clicked);
}
-
[Fact]
[AutoInitShutdown]
public void ChangeHotKey ()
@@ -114,18 +135,18 @@ namespace Terminal.Gui.Views {
btn.Clicked += () => pressed++;
// The Button class supports the Accept command
- Assert.Contains(Command.Accept,btn.GetSupportedCommands ());
+ Assert.Contains (Command.Accept, btn.GetSupportedCommands ());
Application.Top.Add (btn);
Application.Begin (Application.Top);
// default keybinding is Enter which results in keypress
- Application.Driver.SendKeys ('\n',ConsoleKey.Enter,false,false,false);
+ Application.Driver.SendKeys ('\n', ConsoleKey.Enter, false, false, false);
Assert.Equal (1, pressed);
// remove the default keybinding (Enter)
btn.ClearKeybinding (Command.Accept);
-
+
// After clearing the default keystroke the Enter button no longer does anything for the Button
Application.Driver.SendKeys ('\n', ConsoleKey.Enter, false, false, false);
Assert.Equal (1, pressed);
@@ -137,5 +158,32 @@ namespace Terminal.Gui.Views {
Application.Driver.SendKeys ('b', ConsoleKey.B, false, false, false);
Assert.Equal (2, pressed);
}
+
+ [Fact]
+ public void TestAssignTextToButton ()
+ {
+ View b = new Button ();
+ b.Text = "heya";
+ Assert.Equal ("heya", b.Text);
+
+ // with cast
+ Assert.Equal ("heya", ((Button)b).Text);
+ }
+
+ [Fact]
+ public void Setting_Empty_Text_Sets_HoKey_To_KeyNull ()
+ {
+ var btn = new Button ("Test");
+ Assert.Equal ("Test", btn.Text);
+ Assert.Equal (Key.T, btn.HotKey);
+
+ btn.Text = string.Empty;
+ Assert.Equal ("", btn.Text);
+ Assert.Equal (Key.Null, btn.HotKey);
+
+ btn.Text = "Te_st";
+ Assert.Equal ("Te_st", btn.Text);
+ Assert.Equal (Key.S, btn.HotKey);
+ }
}
}