From 269eb017111db9fa18bc9a65a7d17a13b4301017 Mon Sep 17 00:00:00 2001 From: Andrey Akinshin Date: Tue, 26 Dec 2023 15:25:36 +0100 Subject: [PATCH] Fixes #3090. Introduce StatusItem.HotTextSpecifier --- Terminal.Gui/Views/StatusBar.cs | 26 ++++++++++++++++++-------- UnitTests/Views/StatusBarTests.cs | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs index 152ba68fc1..3e0d165d3c 100644 --- a/Terminal.Gui/Views/StatusBar.cs +++ b/Terminal.Gui/Views/StatusBar.cs @@ -16,9 +16,9 @@ namespace Terminal.Gui { /// Each has a title, a shortcut (hotkey), and an that will be invoked when the /// is pressed. /// The will be a global hotkey for the application in the current context of the screen. - /// The colour of the will be changed after each ~. + /// The colour of the will be changed after each ~ (can be customized using ). /// A set to `~F1~ Help` will render as *F1* using and - /// *Help* as . + /// *Help* as . /// public class StatusItem { /// @@ -65,6 +65,15 @@ public StatusItem (Key shortcut, ustring title, Action action, Func canExe /// Function to determine if the action is can be executed or not. public Func CanExecute { get; set; } + /// + /// Gets or sets the rune that toggles the text color between and . + /// The default value is '~'. + /// Therefore, '~F1~ Help' will be rendered as 'F1' using and 'Help' using . + /// In order to use '~' as part of the title (e.g., to denote the home directory as a part of the current directory), + /// should be changed to a different rune. + /// + public Rune HotTextSpecifier { get; set; } = '~'; + /// /// Returns if the status item is enabled. This method is a wrapper around . /// @@ -157,9 +166,10 @@ public override void Redraw (Rect bounds) Driver.SetAttribute (scheme); for (int i = 0; i < Items.Length; i++) { var title = Items [i].Title.ToString (); + var hotTextSpecifier = Items [i].HotTextSpecifier; Driver.SetAttribute (DetermineColorSchemeFor (Items [i])); for (int n = 0; n < Items [i].Title.RuneCount; n++) { - if (title [n] == '~') { + if (title [n] == hotTextSpecifier) { if (Items [i].IsEnabled ()) { scheme = ToggleScheme (scheme); } @@ -197,23 +207,23 @@ public override bool MouseEvent (MouseEvent me) int pos = 1; for (int i = 0; i < Items.Length; i++) { - if (me.X >= pos && me.X < pos + GetItemTitleLength (Items [i].Title)) { + if (me.X >= pos && me.X < pos + GetItemTitleLength (Items [i])) { var item = Items [i]; if (item.IsEnabled ()) { Run (item.Action); } break; } - pos += GetItemTitleLength (Items [i].Title) + 3; + pos += GetItemTitleLength (Items [i]) + 3; } return true; } - int GetItemTitleLength (ustring title) + int GetItemTitleLength (StatusItem item) { int len = 0; - foreach (var ch in title) { - if (ch == '~') + foreach (var ch in item.Title) { + if (ch == item.HotTextSpecifier) continue; len++; } diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs index f713f3106e..63a07ca963 100644 --- a/UnitTests/Views/StatusBarTests.cs +++ b/UnitTests/Views/StatusBarTests.cs @@ -128,6 +128,25 @@ public void Redraw_Output () TestHelpers.AssertDriverContentsAre (expected, output); } + [Fact] + [AutoInitShutdown] + public void Redraw_Output_Custom_HotTextSpecifier () + { + var sb = new StatusBar (new StatusItem [] { + new StatusItem (Key.CtrlMask | Key.T, "~CTRL-T~ _Text_", null), + new StatusItem (Key.CtrlMask | Key.O, "_CTRL-O_ ~/Work", null) { HotTextSpecifier = '_' }, + }); + Application.Top.Add (sb); + + sb.Redraw (sb.Bounds); + + string expected = @$" +CTRL-T _Text_ {Application.Driver.VLine} CTRL-O ~/Work +"; + + TestHelpers.AssertDriverContentsAre (expected, output); + } + [Fact] public void AddItemAt_RemoveItem_Replacing () {