diff --git a/Terminal.Gui/View/ViewSubViews.cs b/Terminal.Gui/View/ViewSubViews.cs index 0e02d5e28..ec5c68593 100644 --- a/Terminal.Gui/View/ViewSubViews.cs +++ b/Terminal.Gui/View/ViewSubViews.cs @@ -74,6 +74,7 @@ public partial class View SuperView._addingView = false; } + // QUESTION: This automatic behavior of setting CanFocus to true on the SuperView is not documented, and is annoying. CanFocus = true; view._tabIndex = _tabIndexes.IndexOf (view); _addingView = false; diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs index af7c84c21..daf661751 100644 --- a/Terminal.Gui/Views/Shortcut.cs +++ b/Terminal.Gui/Views/Shortcut.cs @@ -138,18 +138,10 @@ public class Shortcut : View /// /// Gets or sets the for this . The default is - /// , which is ideal for status bars and toolbars. If set to + /// , which is ideal for status bar, menu bar, and tool bar items If set to /// , - /// the Shortcut will be configured for vertical layout, which is ideal for menus. + /// the Shortcut will be configured for vertical layout, which is ideal for menu items. /// - /// - /// - /// When Horizontal, Key is first, then Help, then Command. When Vertical, Command is first, then Help, then Key. - /// - /// - /// Set to override the default layout. - /// - /// public Orientation Orientation { get => _orientation; @@ -157,26 +149,19 @@ public class Shortcut : View { _orientation = value; - if (value == Orientation.Vertical) - { - AlignmentModes = AlignmentModes.StartToEnd | AlignmentModes.IgnoreFirstOrLast; - } - else - { - AlignmentModes = AlignmentModes.EndToStart | AlignmentModes.IgnoreFirstOrLast; - } + // TODO: Determine what, if anything, is opinionated about the orientation. } } - // The default Orientation is Horizontal thus set this to EndToStart - private AlignmentModes _alignmentModes = AlignmentModes.EndToStart | AlignmentModes.IgnoreFirstOrLast; + private AlignmentModes _alignmentModes = AlignmentModes.StartToEnd | AlignmentModes.IgnoreFirstOrLast; /// /// Gets or sets the for this . /// /// /// - /// Setting will set the to the appropriate value. + /// The default is . This means that the CommandView will be on the left, + /// HelpView in the middle, and KeyView on the right. /// /// public AlignmentModes AlignmentModes @@ -661,7 +646,12 @@ public class Shortcut : View { Action?.Invoke (); - return true; + if (CanFocus) + { + SetFocus (); + } + + return false; } } diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs index 0a6f19c4a..b4df14e6b 100644 --- a/Terminal.Gui/Views/StatusBar.cs +++ b/Terminal.Gui/Views/StatusBar.cs @@ -55,17 +55,23 @@ public class StatusBar : Bar } } - /// public override View Add (View view) { + // Call base first, because otherwise it resets CanFocus to true + base.Add (view); + view.CanFocus = false; if (view is Shortcut shortcut) { shortcut.KeyBindingScope = KeyBindingScope.Application; + + // TODO: not happy about using AlignmentModes for this. Too implied. + // TODO: instead, add a property (a style enum?) to Shortcut to control this + shortcut.AlignmentModes = AlignmentModes.EndToStart; } - return base.Add (view); + return view; } } diff --git a/UICatalog/Scenarios/Bars.cs b/UICatalog/Scenarios/Bars.cs index 73ef5a546..331bc1f0c 100644 --- a/UICatalog/Scenarios/Bars.cs +++ b/UICatalog/Scenarios/Bars.cs @@ -14,7 +14,7 @@ public class Bars : Scenario public override void Main () { Application.Init (); - Window app = new (); + Toplevel app = new (); app.Loaded += App_Loaded; @@ -28,31 +28,87 @@ public class Bars : Scenario // QuitKey and it only sticks if changed after init private void App_Loaded (object sender, EventArgs e) { - Application.QuitKey = Key.Z.WithCtrl; Application.Top.Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"; ObservableCollection eventSource = new (); ListView eventLog = new ListView () { + Title = "Event Log", X = Pos.AnchorEnd (), - Width = 50, - Height = Dim.Fill (6), + Width = Dim.Auto(), + Height = Dim.Fill (), // Make room for some wide things ColorScheme = Colors.ColorSchemes ["Toplevel"], Source = new ListWrapper (eventSource) }; + eventLog.Border.Thickness = new (0, 1, 0, 0); Application.Top.Add (eventLog); + FrameView menuBarLikeExamples = new () + { + Title = "MenuBar-Like Examples", + X = 0, + Y = 0, + Width = Dim.Fill () - Dim.Width (eventLog), + Height = 10, + }; + Application.Top.Add (menuBarLikeExamples); + + Label label = new Label () + { + Title = " Bar:", + X = 0, + Y = Pos.AnchorEnd () - 6 + }; + menuBarLikeExamples.Add (label); + + Bar bar = new Bar + { + Id = "menuBar-like", + X = Pos.Right (label), + Y = Pos.Top (label), + Width = Dim.Fill (), + Height = 1,//Dim.Auto (DimAutoStyle.Content), + Orientation = Orientation.Horizontal, + }; + + ConfigMenuBar (bar); + menuBarLikeExamples.Add (bar); + + label = new Label () + { + Title = " MenuBar:", + X = 0, + Y = Pos.Bottom(bar) + }; + menuBarLikeExamples.Add (label); + + //bar = new MenuBarv2 + //{ + // Id = "menuBar", + // Width = Dim.Fill (), + // Height = 1,//Dim.Auto (DimAutoStyle.Content), + // Orientation = Orientation.Horizontal, + //}; + + //ConfigMenuBar (bar); + //menuBarLikeExamples.Add (bar); + + FrameView menuLikeExamples = new () + { + Title = "Menu-Like Examples", + X = 0, + Y = Pos.Bottom (menuBarLikeExamples), + Width = Dim.Fill () - Dim.Width (eventLog), + Height = 10, + }; + Application.Top.Add (menuLikeExamples); + var shortcut1 = new Shortcut { Title = "_Zigzag", Key = Key.G.WithCtrl, Text = "Gonna zig zag", }; - shortcut1.Accept += (s, e) => - { - eventSource.Add ($"Accept: {s}"); - eventLog.MoveDown (); - }; var shortcut2 = new Shortcut { @@ -61,49 +117,6 @@ public class Bars : Scenario Key = Key.G.WithAlt, }; - //var shortcut3 = new Shortcut - //{ - // Title = "Shortcut3", - // Key = Key.D3.WithCtrl, - // Text = "Number Three", - // KeyBindingScope = KeyBindingScope.Application, - // Command = Command.Accept, - //}; - - //shortcut3.Accept += (s, e) => - // { - // eventSource.Add ($"Accept: {s}"); - // eventLog.MoveDown (); - // }; - - //var shortcut4 = new Shortcut - //{ - // Title = "Shortcut4", - // Text = "Number 4", - // Key = Key.F4, - // KeyBindingScope = KeyBindingScope.Application, - // Command = Command.Accept, - //}; - - //var cb = new CheckBox () - //{ - // Title = "Hello",// shortcut4.Text - //}; - - //cb.Toggled += (s, e) => - // { - // eventSource.Add ($"Toggled: {s}"); - // eventLog.MoveDown (); - // }; - - //shortcut4.CommandView = cb; - - //shortcut4.Accept += (s, e) => - // { - // eventSource.Add ($"Accept: {s}"); - // eventLog.MoveDown (); - // }; - var vBar = new Bar { X = 2, @@ -113,44 +126,41 @@ public class Bars : Scenario }; vBar.Add (shortcut1, shortcut2); - ////CheckBox hello = new () - ////{ - //// Title = "Hello", - //// X = 0, - //// Y = 1, - ////}; - ////Application.Top.Add (hello); - ////hello.Toggled += (s, e) => - //// { - //// eventSource.Add ($"Toggled: {s}"); - //// eventLog.MoveDown (); - //// }; - - - Application.Top.Add (vBar); + menuLikeExamples.Add (vBar); // BUGBUG: This should not be needed - Application.Top.LayoutSubviews (); + menuLikeExamples.LayoutSubviews (); // SetupMenuBar (); //SetupContentMenu (); - Label label = new Label () + + FrameView statusBarLikeExamples = new () + { + Title = "StatusBar-Like Examples", + X = 0, + Y = Pos.AnchorEnd (), + Width = Dim.Width (menuLikeExamples), + Height = 10, + }; + Application.Top.Add (statusBarLikeExamples); + + label = new Label () { Title = " Bar:", X = 0, Y = Pos.AnchorEnd () - 6 }; - Application.Top.Add (label); - var bar = new Bar - { - Id = "bar", - X = Pos.Right (label), - Y = Pos.Top (label), - Width = Dim.Fill (), - Orientation = Orientation.Horizontal, - }; - ConfigStatusBar (bar); - Application.Top.Add (bar); + statusBarLikeExamples.Add (label); + //bar = new Bar + //{ + // Id = "statusBar-like", + // X = Pos.Right (label), + // Y = Pos.Top (label), + // Width = Dim.Fill (), + // Orientation = Orientation.Horizontal, + //}; + //ConfigStatusBar (bar); + //statusBarLikeExamples.Add (bar); label = new Label () { @@ -158,8 +168,8 @@ public class Bars : Scenario X = 0, Y = Pos.AnchorEnd () - 3 }; - Application.Top.Add (label); - bar = new StatusBar() + statusBarLikeExamples.Add (label); + bar = new StatusBar () { Id = "statusBar", X = Pos.Right (label), @@ -168,17 +178,20 @@ public class Bars : Scenario Orientation = Orientation.Horizontal, }; ConfigStatusBar (bar); - Application.Top.Add (bar); + statusBarLikeExamples.Add (bar); - foreach (Bar barView in Application.Top.Subviews.Where (b => b is Bar)!) + foreach (FrameView frameView in Application.Top.Subviews.Where (f => f is FrameView)!) { - foreach (Shortcut sh in barView.Subviews.Where (s => s is Shortcut)!) + foreach (Bar barView in frameView.Subviews.Where (b => b is Bar)!) { - sh.Accept += (o, args) => - { - eventSource.Add ($"Accept: {sh!.SuperView.Id} {sh!.CommandView.Text}"); - eventLog.MoveDown (); - }; + foreach (Shortcut sh in barView.Subviews.Where (s => s is Shortcut)!) + { + sh.Accept += (o, args) => + { + eventSource.Add ($"Accept: {sh!.SuperView.Id} {sh!.CommandView.Text}"); + eventLog.MoveDown (); + }; + } } } } @@ -331,108 +344,20 @@ public class Bars : Scenario ((View)(sender)).LayoutSubviews (); } - private void SetupMenuBar () + private void ConfigMenuBar (Bar bar) { - var menuBar = new Bar - { - Id = "menuBar", - Width = Dim.Fill (), - Height = 1,//Dim.Auto (DimAutoStyle.Content), - Orientation = Orientation.Horizontal, - }; - var fileMenuBarItem = new Shortcut { Title = "_File", - KeyBindingScope = KeyBindingScope.Application, - Key = Key.F.WithAlt, }; fileMenuBarItem.KeyView.Visible = false; var editMenuBarItem = new Shortcut { Title = "_Edit", - - KeyBindingScope = KeyBindingScope.HotKey, - }; - - editMenuBarItem.Accept += (s, e) => { }; - //editMenu.HelpView.Visible = false; - //editMenu.KeyView.Visible = false; - - menuBar.Add (fileMenuBarItem, editMenuBarItem); - menuBar.Initialized += Menu_Initialized; - Application.Top.Add (menuBar); - - var fileMenu = new Bar - { - X = 1, - Y = 1, - Orientation = Orientation.Vertical, - // Modal = true, - Visible = false, - }; - - var newShortcut = new Shortcut - { - Title = "_New...", - Text = "Create a new file", - Key = Key.N.WithCtrl - }; - newShortcut.Border.Thickness = new Thickness (0, 1, 0, 0); - - var openShortcut = new Shortcut - { - Title = "_Open...", - Text = "Show the File Open Dialog", - Key = Key.O.WithCtrl - }; - - var saveShortcut = new Shortcut - { - Title = "_Save...", - Text = "Save", - Key = Key.S.WithCtrl, - Enabled = false - }; - - var exitShortcut = new Shortcut - { - Title = "E_xit", - Text = "Exit", - Key = Key.X.WithCtrl, - }; - exitShortcut.Border.Thickness = new Thickness (0, 1, 0, 1); - - fileMenu.Add (newShortcut, openShortcut, saveShortcut, exitShortcut); - - View prevFocus = null; - fileMenuBarItem.Accept += (s, e) => - { - if (fileMenu.Visible) - { - // fileMenu.RequestStop (); - prevFocus?.SetFocus (); - return; - } - - //fileMenu.Visible = !fileMenu.Visible; - var sender = s as Shortcut; - var screen = sender.FrameToScreen (); - fileMenu.X = screen.X; - fileMenu.Y = screen.Y + 1; - fileMenu.Visible = true; - prevFocus = Application.Top.Focused; - fileMenuBarItem.SetFocus (); - //Application.Run (fileMenu); - fileMenu.Visible = false; - }; - - Application.Top.Closed += (s, e) => - { - fileMenu.Dispose (); }; + bar.Add (fileMenuBarItem, editMenuBarItem); } private void ConfigStatusBar (Bar bar) @@ -442,8 +367,7 @@ public class Bars : Scenario Height = Dim.Auto (DimAutoStyle.Content, 3), Text = "Quit", Title = "Q_uit", - Key = Application.QuitKey, - KeyBindingScope = KeyBindingScope.Application, + Key = Key.Z.WithCtrl, }; bar.Add (shortcut); @@ -453,7 +377,6 @@ public class Bars : Scenario Text = "Help Text", Title = "Help", Key = Key.F1, - KeyBindingScope = KeyBindingScope.HotKey, }; bar.Add (shortcut); @@ -462,9 +385,9 @@ public class Bars : Scenario { Title = "_Show/Hide", Key = Key.F10, - KeyBindingScope = KeyBindingScope.Application, CommandView = new CheckBox { + CanFocus = false, Text = "_Show/Hide" }, }; diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index cf4c261d9..be453a66b 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -447,70 +447,73 @@ internal class UICatalogApp ] }; - ShVersion = new () - { - Title = "Version Info", - CanFocus = false, - - }; - - StatusBar = new () - { - Visible = ShowStatusBar, - }; - StatusBar.AlignmentModes = AlignmentModes.StartToEnd | AlignmentModes.IgnoreFirstOrLast; - - Shortcut statusBarShortcut = new Shortcut () - { - Key = Key.F10, - Title = "Show/Hide Status Bar", - }; - statusBarShortcut.Accept += (sender, args) => - { - StatusBar.Visible = !StatusBar.Visible; - }; - - ShForce16Colors = new Shortcut () - { - CommandView = new CheckBox () - { - Title = "16 color mode", - Checked = Application.Force16Colors, - CanFocus = false, - }, HelpText = "", - Key = Key.F6, - }; - ShForce16Colors.Accept += (sender, args) => - { - ((CheckBox)ShForce16Colors.CommandView).Checked = Application.Force16Colors = (bool)!((CheckBox)ShForce16Colors.CommandView).Checked!; - MiForce16Colors.Checked = Application.Force16Colors; - Application.Refresh (); - - }; - - //ShDiagnostics = new Shortcut () + //StatusBar = new () //{ - // HelpText = "Diagnostic flags", - // CommandView = new RadioGroup() - // { - // RadioLabels = ["Off", "Ruler", "Padding", "MouseEnter"], - - // CanFocus = false, - // Orientation = Orientation.Vertical, - // } + // Visible = ShowStatusBar, //}; - StatusBar.Add ( - new Shortcut () + if (StatusBar is { }) + { + ShVersion = new () { - Title = "Quit", - Key = Application.QuitKey, - }, - statusBarShortcut, - ShForce16Colors, - //ShDiagnostics, - ShVersion - ); + Title = "Version Info", + CanFocus = false, + + }; + + Shortcut statusBarShortcut = new Shortcut () + { + Key = Key.F10, + Title = "Show/Hide Status Bar", + }; + statusBarShortcut.Accept += (sender, args) => { StatusBar.Visible = !StatusBar.Visible; }; + + ShForce16Colors = new Shortcut () + { + CommandView = new CheckBox () + { + Title = "16 color mode", + Checked = Application.Force16Colors, + CanFocus = false, + }, + HelpText = "", + Key = Key.F6, + }; + + ShForce16Colors.Accept += (sender, args) => + { + ((CheckBox)ShForce16Colors.CommandView).Checked = + Application.Force16Colors = (bool)!((CheckBox)ShForce16Colors.CommandView).Checked!; + MiForce16Colors.Checked = Application.Force16Colors; + Application.Refresh (); + + }; + + //ShDiagnostics = new Shortcut () + //{ + // HelpText = "Diagnostic flags", + // CommandView = new RadioGroup() + // { + // RadioLabels = ["Off", "Ruler", "Padding", "MouseEnter"], + + // CanFocus = false, + // Orientation = Orientation.Vertical, + // } + //}; + + StatusBar.Add ( + new Shortcut () + { + Title = "Quit", + Key = Application.QuitKey, + }, + statusBarShortcut, + ShForce16Colors, + + //ShDiagnostics, + ShVersion + ); + } // Create the Category list view. This list never changes. CategoryList = new () @@ -615,7 +618,11 @@ internal class UICatalogApp Add (ScenarioList); Add (MenuBar); - Add (StatusBar); + + if (StatusBar is { }) + { + Add (StatusBar); + } Loaded += LoadedHandler; Unloaded += UnloadedHandler; @@ -651,16 +658,14 @@ internal class UICatalogApp MenuBar.Menus [0].Children [0].Shortcut = (KeyCode)Application.QuitKey; - ((Shortcut)StatusBar.Subviews [0]).Key = Application.QuitKey; + if (StatusBar is { }) + { + ((Shortcut)StatusBar.Subviews [0]).Key = Application.QuitKey; + StatusBar.Visible = ShowStatusBar; + } MiIsMouseDisabled!.Checked = Application.IsMouseDisabled; - int height = ShowStatusBar ? 1 : 0; // + (MenuBar.Visible ? 1 : 0); - - //ContentPane.Height = Dim.Fill (height); - - StatusBar.Visible = ShowStatusBar; - Application.Top.SetNeedsDisplay (); } @@ -1032,7 +1037,11 @@ internal class UICatalogApp ConfigChanged (); MiIsMouseDisabled!.Checked = Application.IsMouseDisabled; - ShVersion.Title = $"{RuntimeEnvironment.OperatingSystem} {RuntimeEnvironment.OperatingSystemVersion}, {Driver.GetVersionInfo ()}"; + + if (ShVersion is { }) + { + ShVersion.Title = $"{RuntimeEnvironment.OperatingSystem} {RuntimeEnvironment.OperatingSystemVersion}, {Driver.GetVersionInfo ()}"; + } if (_selectedScenario != null) { @@ -1045,18 +1054,21 @@ internal class UICatalogApp ScenarioList.SetFocus (); } - StatusBar.VisibleChanged += (s, e) => - { - ShowStatusBar = StatusBar.Visible; + if (StatusBar is { }) + { + StatusBar.VisibleChanged += (s, e) => + { + ShowStatusBar = StatusBar.Visible; - int height = StatusBar.Visible ? 1 : 0; - CategoryList.Height = Dim.Fill (height); - ScenarioList.Height = Dim.Fill (height); + int height = StatusBar.Visible ? 1 : 0; + CategoryList.Height = Dim.Fill (height); + ScenarioList.Height = Dim.Fill (height); - // ContentPane.Height = Dim.Fill (height); - LayoutSubviews (); - SetSubViewNeedsDisplay (); - }; + // ContentPane.Height = Dim.Fill (height); + LayoutSubviews (); + SetSubViewNeedsDisplay (); + }; + } Loaded -= LoadedHandler; CategoryList.EnsureSelectedItemVisible ();