Changed Button Text property to use override instead of new. (#1622)

* Changed Button Text property to use override instead of new.

* Fixing HotKey behavior.
This commit is contained in:
BDisp
2022-03-05 02:05:27 +00:00
committed by GitHub
parent a9a0d176c1
commit 4281030361
3 changed files with 130 additions and 35 deletions

View File

@@ -186,12 +186,12 @@ namespace Terminal.Gui {
/// <summary>
/// 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.
/// </summary>
public Key HotKey { get => textFormatter.HotKey; set => textFormatter.HotKey = value; }
public virtual Key HotKey { get => textFormatter.HotKey; set => textFormatter.HotKey = value; }
/// <summary>
/// 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'.
/// </summary>
public Rune HotKeySpecifier { get => textFormatter.HotKeySpecifier; set => textFormatter.HotKeySpecifier = value; }
public virtual Rune HotKeySpecifier { get => textFormatter.HotKeySpecifier; set => textFormatter.HotKeySpecifier = value; }
/// <summary>
/// This is the global setting that can be used as a global shortcut to invoke an action if provided.

View File

@@ -33,6 +33,7 @@ namespace Terminal.Gui {
public class Button : View {
ustring text;
bool is_default;
TextFormatter textFormatter = new TextFormatter ();
/// <summary>
/// Initializes a new instance of <see cref="Button"/> using <see cref="LayoutStyle.Computed"/> 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);
}
}
}
/// <summary>
/// The text displayed by this <see cref="Button"/>.
/// </summary>
public new ustring Text {
/// <inheritdoc/>>
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 {
}
}
/// <inheritdoc/>
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;
}
}
}
/// <inheritdoc/>
public override Rune HotKeySpecifier {
get => hotKeySpecifier;
set {
hotKeySpecifier = textFormatter.HotKeySpecifier = value;
}
}
/// <inheritdoc/>
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 ();
}
/// <inheritdoc/>
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);
}
}
///<inheritdoc/>
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;
}

View File

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