Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #3090. Introduce StatusItem.HotTextSpecifier #3093

Merged
merged 3 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions Terminal.Gui/Views/StatusBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ namespace Terminal.Gui {
/// Each <see cref="StatusItem"/> has a title, a shortcut (hotkey), and an <see cref="Action"/> that will be invoked when the
/// <see cref="StatusItem.Shortcut"/> is pressed.
/// The <see cref="StatusItem.Shortcut"/> will be a global hotkey for the application in the current context of the screen.
/// The colour of the <see cref="StatusItem.Title"/> will be changed after each ~.
/// The colour of the <see cref="StatusItem.Title"/> will be changed after each ~ (can be customized using <see cref="HotTextSpecifier"/>).
/// A <see cref="StatusItem.Title"/> set to `~F1~ Help` will render as *F1* using <see cref="ColorScheme.HotNormal"/> and
/// *Help* as <see cref="ColorScheme.HotNormal"/>.
/// *Help* as <see cref="ColorScheme.Normal"/>.
/// </summary>
public class StatusItem {
/// <summary>
Expand Down Expand Up @@ -65,6 +65,15 @@ public StatusItem (Key shortcut, ustring title, Action action, Func<bool> canExe
/// <value>Function to determine if the action is can be executed or not.</value>
public Func<bool> CanExecute { get; set; }

/// <summary>
/// Gets or sets the rune that toggles the text color between <see cref="ColorScheme.Normal"/> and <see cref="ColorScheme.HotNormal"/>.
/// The default value is '~'.
/// Therefore, '~F1~ Help' will be rendered as 'F1' using <see cref="ColorScheme.HotNormal"/> and 'Help' using <see cref="ColorScheme.Normal"/>.
/// In order to use '~' as part of the title (e.g., to denote the home directory as a part of the current directory),
/// <see cref="HotTextSpecifier"/> should be changed to a different rune.
/// </summary>
public Rune HotTextSpecifier { get; set; } = '~';

/// <summary>
/// Returns <see langword="true"/> if the status item is enabled. This method is a wrapper around <see cref="CanExecute"/>.
/// </summary>
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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++;
}
Expand Down
19 changes: 19 additions & 0 deletions UnitTests/Views/StatusBarTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
{
Expand Down
Loading