diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs index 8fb9a2156..1d66b853d 100644 --- a/Terminal.Gui/Views/StatusBar.cs +++ b/Terminal.Gui/Views/StatusBar.cs @@ -27,11 +27,13 @@ namespace Terminal.Gui { /// Shortcut to activate the . /// Title for the . /// Action to invoke when the is activated. - public StatusItem (Key shortcut, string title, Action action) + /// Function to determine if the action can currently be executed. + public StatusItem (Key shortcut, string title, Action action, Func canExecute = null) { Title = title ?? ""; Shortcut = shortcut; Action = action; + CanExecute = canExecute; } /// @@ -54,7 +56,22 @@ namespace Terminal.Gui { /// Gets or sets the action to be invoked when the statusbar item is triggered /// /// Action to invoke. - public Action Action { get; } + public Action Action { get; set; } + + /// + /// Gets or sets the action to be invoked to determine if the can be triggered. + /// If returns the status item will be enabled. Otherwise, it will be disabled. + /// + /// Function to determine if the action is can be executed or not. + public Func CanExecute { get; set; } + + /// + /// Returns if the status item is enabled. This method is a wrapper around . + /// + public bool IsEnabled () + { + return CanExecute == null ? true : CanExecute (); + } /// /// Gets or sets arbitrary data for the status item. @@ -116,6 +133,17 @@ namespace Terminal.Gui { return result; } + Attribute DetermineColorSchemeFor (StatusItem item) + { + if (item != null) { + if (item.IsEnabled ()) { + return GetNormalColor (); + } + return ColorScheme.Disabled; + } + return GetNormalColor (); + } + /// public override void OnDrawContent (Rect contentArea) { @@ -130,9 +158,12 @@ namespace Terminal.Gui { Driver.SetAttribute (scheme); for (int i = 0; i < Items.Length; i++) { var title = Items [i].Title; + Driver.SetAttribute (DetermineColorSchemeFor (Items [i])); for (int n = 0; n < Items [i].Title.GetRuneCount (); n++) { if (title [n] == '~') { - scheme = ToggleScheme (scheme); + if (Items [i].IsEnabled ()) { + scheme = ToggleScheme (scheme); + } continue; } Driver.AddRune ((Rune)title [n]); @@ -150,7 +181,9 @@ namespace Terminal.Gui { { foreach (var item in Items) { if (kb.Key == item.Shortcut) { - Run (item.Action); + if (item.IsEnabled ()) { + Run (item.Action); + } return true; } } @@ -166,7 +199,10 @@ namespace Terminal.Gui { int pos = 1; for (int i = 0; i < Items.Length; i++) { if (me.X >= pos && me.X < pos + GetItemTitleLength (Items [i].Title)) { - Run (Items [i].Action); + var item = Items [i]; + if (item.IsEnabled ()) { + Run (item.Action); + } break; } pos += GetItemTitleLength (Items [i].Title) + 3; diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs index 06ef9d597..d2e81ead1 100644 --- a/UnitTests/Views/StatusBarTests.cs +++ b/UnitTests/Views/StatusBarTests.cs @@ -23,7 +23,7 @@ namespace Terminal.Gui.ViewsTests { } [Fact] - public void StatusBar_Contructor_Default () + public void StatusBar_Constructor_Default () { var sb = new StatusBar (); @@ -160,5 +160,43 @@ CTRL-O Open {CM.Glyphs.VLine} CTRL-Q Quit Assert.Equal ("~^A~ Save As", sb.Items [1].Title); Assert.Equal ("~^Q~ Quit", sb.Items [^1].Title); } + + [Fact, AutoInitShutdown] + public void CanExecute_ProcessHotKey () + { + Window win = null; + var statusBar = new StatusBar (new StatusItem [] { + new StatusItem (Key.CtrlMask | Key.N, "~^N~ New", New, CanExecuteNew), + new StatusItem (Key.CtrlMask | Key.C, "~^C~ Close", Close, CanExecuteClose) + }); + var top = Application.Top; + top.Add (statusBar); + + bool CanExecuteNew () => win == null; + + void New () + { + win = new Window (); + } + + bool CanExecuteClose () => win != null; + + void Close () + { + win = null; + } + + Application.Begin (top); + + Assert.Null (win); + Assert.True (CanExecuteNew ()); + Assert.False (CanExecuteClose ()); + + Assert.True (top.ProcessHotKey (new KeyEvent (Key.N | Key.CtrlMask, new KeyModifiers () { Alt = true }))); + Application.MainLoop.RunIteration (); + Assert.NotNull (win); + Assert.False (CanExecuteNew ()); + Assert.True (CanExecuteClose ()); + } } }