From 4e0e5d1e7214f5bb9eb0b7da48e162c7cca28c10 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 17 Jun 2024 16:59:18 -0700 Subject: [PATCH] Beefed up Bars scenario. Added MenuBarv2 Added Menuv2 --- Terminal.Gui/Views/Bar.cs | 37 ++------- Terminal.Gui/Views/MenuBarv2.cs | 108 ++++++++++++++++++++++++++ Terminal.Gui/Views/Menuv2.cs | 109 +++++++++++++++++++++++++++ Terminal.Gui/Views/Shortcut.cs | 10 ++- UICatalog/Scenarios/Bars.cs | 129 +++++++++++++++++++++----------- 5 files changed, 314 insertions(+), 79 deletions(-) create mode 100644 Terminal.Gui/Views/MenuBarv2.cs create mode 100644 Terminal.Gui/Views/Menuv2.cs diff --git a/Terminal.Gui/Views/Bar.cs b/Terminal.Gui/Views/Bar.cs index aed8cd779..fbff2d814 100644 --- a/Terminal.Gui/Views/Bar.cs +++ b/Terminal.Gui/Views/Bar.cs @@ -159,21 +159,6 @@ public class Bar : View break; case Orientation.Vertical: - // CommandView is aligned left, HelpView is aligned right, KeyView is aligned right - // All CommandView's are the same width, all HelpView's are the same width, - // all KeyView's are the same width - - var minKeyWidth = 0; - - List shortcuts = Subviews.Where (s => s is Shortcut && s.Visible).Cast ().ToList (); - - foreach (Shortcut shortcut in shortcuts) - { - // Let AutoSize do its thing to get the minimum width of each CommandView and HelpView - //shortcut.CommandView.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); - minKeyWidth = int.Max (minKeyWidth, shortcut.KeyView.Text.GetColumns ()); - } - // Set the overall size of the Bar and arrange the views vertically var maxBarItemWidth = 0; var totalHeight = 0; @@ -182,10 +167,7 @@ public class Bar : View { View barItem = Subviews [index]; - if (barItem is Shortcut scBarItem) - { - scBarItem.MinimumKeyViewSize = minKeyWidth; - } + barItem.ColorScheme = ColorScheme; if (!barItem.Visible) { @@ -204,23 +186,16 @@ public class Bar : View prevBarItem = barItem; - if (barItem is Shortcut shortcut) - { - maxBarItemWidth = Math.Max (maxBarItemWidth, shortcut.Frame.Width); - } - else - { - maxBarItemWidth = Math.Max (maxBarItemWidth, barItem.Frame.Width); - } + //maxBarItemWidth = Math.Max (maxBarItemWidth, barItem.Frame.Width); barItem.X = 0; totalHeight += barItem.Frame.Height; } - foreach (Shortcut shortcut in shortcuts) - { - shortcut.Width = maxBarItemWidth; - } + //foreach (Shortcut shortcut in shortcuts) + //{ + // shortcut.Width = maxBarItemWidth; + //} Height = Dim.Auto (DimAutoStyle.Content, totalHeight); diff --git a/Terminal.Gui/Views/MenuBarv2.cs b/Terminal.Gui/Views/MenuBarv2.cs new file mode 100644 index 000000000..2b06ac1e1 --- /dev/null +++ b/Terminal.Gui/Views/MenuBarv2.cs @@ -0,0 +1,108 @@ +using System; +using System.Reflection; + +namespace Terminal.Gui; + +/// +/// A menu bar is a that snaps to the top of a displaying set of +/// s. +/// +public class MenuBarv2 : Bar +{ + /// + public MenuBarv2 () : this ([]) { } + + /// + public MenuBarv2 (IEnumerable shortcuts) : base (shortcuts) + { + Y = 0; + Width = Dim.Fill (); + Height = Dim.Auto (DimAutoStyle.Content, 1); + BorderStyle = LineStyle.Dashed; + ColorScheme = Colors.ColorSchemes ["Menu"]; + Orientation = Orientation.Horizontal; + + LayoutStarted += MenuBarv2_LayoutStarted; + } + + // MenuBarv2 arranges the items horizontally. + // The first item has no left border, the last item has no right border. + // The Shortcuts are configured with the command, help, and key views aligned in reverse order (EndToStart). + private void MenuBarv2_LayoutStarted (object sender, LayoutEventArgs e) + { + var minKeyWidth = 0; + + List shortcuts = Subviews.Where (s => s is Shortcut && s.Visible).Cast ().ToList (); + + foreach (Shortcut shortcut in shortcuts) + { + // Let AutoSize do its thing to get the minimum width of each CommandView and HelpView + //shortcut.CommandView.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); + minKeyWidth = int.Max (minKeyWidth, shortcut.KeyView.Text.GetColumns ()); + } + + View prevBarItem = null; + var maxBarItemWidth = 0; + + for (int index = 0; index < Subviews.Count; index++) + { + View barItem = Subviews [index]; + + if (!barItem.Visible) + { + continue; + } + + if (barItem is Shortcut scBarItem) + { + scBarItem.MinimumKeyViewSize = minKeyWidth; + } + + if (index == Subviews.Count - 1) + { + barItem.Border.Thickness = new Thickness (0, 0, 0, 0); + } + else + { + barItem.Border.Thickness = new Thickness (0, 0, 0, 0); + } + + if (barItem is Shortcut shortcut) + { + // shortcut.Min + // shortcut.Orientation = Orientation.Vertical; + } + + maxBarItemWidth = Math.Max (maxBarItemWidth, barItem.Frame.Width); + + } + + foreach (Shortcut shortcut in shortcuts) + { + shortcut.Width = maxBarItemWidth; + } + } + + /// + public override View Add (View view) + { + // Call base first, because otherwise it resets CanFocus to true + base.Add (view); + + view.CanFocus = true; + + 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; + + shortcut.KeyView.Visible = false; + shortcut.HelpView.Visible = false; + } + + return view; + } +} diff --git a/Terminal.Gui/Views/Menuv2.cs b/Terminal.Gui/Views/Menuv2.cs new file mode 100644 index 000000000..d2f3eb4af --- /dev/null +++ b/Terminal.Gui/Views/Menuv2.cs @@ -0,0 +1,109 @@ +using System; +using System.Reflection; + +namespace Terminal.Gui; + +/// +/// +public class Menuv2 : Bar +{ + /// + public Menuv2 () : this ([]) { } + + /// + public Menuv2 (IEnumerable shortcuts) : base (shortcuts) + { + Orientation = Orientation.Vertical; + Width = Dim.Auto (); + Height = Dim.Auto (DimAutoStyle.Content, 1); + ColorScheme = Colors.ColorSchemes ["Menu"]; + + LayoutStarted += Menuv2_LayoutStarted; + } + + // Menuv2 arranges the items horizontally. + // The first item has no left border, the last item has no right border. + // The Shortcuts are configured with the command, help, and key views aligned in reverse order (EndToStart). + private void Menuv2_LayoutStarted (object sender, LayoutEventArgs e) + { + var minKeyWidth = 0; + + List shortcuts = Subviews.Where (s => s is Shortcut && s.Visible).Cast ().ToList (); + + foreach (Shortcut shortcut in shortcuts) + { + // Let AutoSize do its thing to get the minimum width of each CommandView and HelpView + //shortcut.CommandView.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); + minKeyWidth = int.Max (minKeyWidth, shortcut.KeyView.Text.GetColumns ()); + } + + View prevBarItem = null; + var maxBarItemWidth = 0; + + for (int index = 0; index < Subviews.Count; index++) + { + View barItem = Subviews [index]; + + if (!barItem.Visible) + { + continue; + } + + if (barItem is Shortcut scBarItem) + { + scBarItem.MinimumKeyViewSize = minKeyWidth; + } + + if (index == Subviews.Count - 1) + { + barItem.Border.Thickness = new Thickness (1, 0, 1, 1); + } + else if (index == 0) + { + barItem.Border.Thickness = new Thickness (1, 1, 1, 0); + } + else + { + barItem.Border.Thickness = new Thickness (1, 0, 1, 0); + } + + if (barItem is Shortcut shortcut) + { + // shortcut.Min + // shortcut.Orientation = Orientation.Vertical; + } + + prevBarItem = barItem; + // HACK: This should not be needed + barItem.SetRelativeLayout (GetContentSize ()); + + maxBarItemWidth = Math.Max (maxBarItemWidth, barItem.Frame.Width); + } + + foreach (Shortcut shortcut in shortcuts) + { + shortcut.Width = maxBarItemWidth; + } + } + + /// + public override View Add (View view) + { + // Call base first, because otherwise it resets CanFocus to true + base.Add (view); + + view.CanFocus = true; + + 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 view; + } +} diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs index eeaddcd70..9002c6ef0 100644 --- a/Terminal.Gui/Views/Shortcut.cs +++ b/Terminal.Gui/Views/Shortcut.cs @@ -634,9 +634,8 @@ public class Shortcut : View break; case KeyBindingScope.HotKey: - CommandView.InvokeCommand (Command.HotKey); - handled = false; - + CommandView.InvokeCommand (Command.HotKey); + handled = false; break; } @@ -648,7 +647,7 @@ public class Shortcut : View if (CanFocus) { - CommandView.SetFocus (); + SetFocus (); } return true; @@ -718,10 +717,12 @@ public class Shortcut : View } } + View _lastFocusedView; /// public override bool OnEnter (View view) { SetColors (); + _lastFocusedView = view; return base.OnEnter (view); } @@ -730,6 +731,7 @@ public class Shortcut : View public override bool OnLeave (View view) { SetColors (); + _lastFocusedView = this; return base.OnLeave (view); } diff --git a/UICatalog/Scenarios/Bars.cs b/UICatalog/Scenarios/Bars.cs index bba0ba615..4014d5b2f 100644 --- a/UICatalog/Scenarios/Bars.cs +++ b/UICatalog/Scenarios/Bars.cs @@ -35,7 +35,7 @@ public class Bars : Scenario { Title = "Event Log", X = Pos.AnchorEnd (), - Width = Dim.Auto(), + Width = Dim.Auto (), Height = Dim.Fill (), // Make room for some wide things ColorScheme = Colors.ColorSchemes ["Toplevel"], Source = new ListWrapper (eventSource) @@ -49,7 +49,7 @@ public class Bars : Scenario X = 0, Y = 0, Width = Dim.Fill () - Dim.Width (eventLog), - Height = 10, + Height = Dim.Percent(33), }; Application.Top.Add (menuBarLikeExamples); @@ -57,7 +57,7 @@ public class Bars : Scenario { Title = " Bar:", X = 0, - Y = Pos.AnchorEnd () - 6 + Y = 0, }; menuBarLikeExamples.Add (label); @@ -67,8 +67,6 @@ public class Bars : Scenario X = Pos.Right (label), Y = Pos.Top (label), Width = Dim.Fill (), - Height = 1,//Dim.Auto (DimAutoStyle.Content), - Orientation = Orientation.Horizontal, }; ConfigMenuBar (bar); @@ -78,61 +76,68 @@ public class Bars : Scenario { Title = " MenuBar:", X = 0, - Y = Pos.Bottom(bar) + Y = Pos.Bottom (bar) + 1 }; menuBarLikeExamples.Add (label); - //bar = new MenuBarv2 - //{ - // Id = "menuBar", - // Width = Dim.Fill (), - // Height = 1,//Dim.Auto (DimAutoStyle.Content), - // Orientation = Orientation.Horizontal, - //}; + bar = new MenuBarv2 + { + Id = "menuBar", + X = Pos.Right (label), + Y = Pos.Top (label), + }; - //ConfigMenuBar (bar); - //menuBarLikeExamples.Add (bar); + ConfigMenuBar (bar); + menuBarLikeExamples.Add (bar); FrameView menuLikeExamples = new () { Title = "Menu-Like Examples", X = 0, - Y = Pos.Bottom (menuBarLikeExamples), + Y = Pos.Center (), Width = Dim.Fill () - Dim.Width (eventLog), - Height = 10, + Height = Dim.Percent (33), }; Application.Top.Add (menuLikeExamples); - var shortcut1 = new Shortcut + label = new Label () { - Title = "_Zigzag", - Key = Key.G.WithCtrl, - Text = "Gonna zig zag", + Title = "Bar:", + X = 0, + Y = 0, }; + menuLikeExamples.Add (label); - var shortcut2 = new Shortcut + bar = new Bar { - Title = "Za_G", - Text = "Gonna zag", - Key = Key.G.WithAlt, - }; - - var vBar = new Bar - { - X = 2, - Y = 2, + Id = "menu-like", + X = 0, + Y = Pos.Bottom(label), + //Width = Dim.Percent (40), Orientation = Orientation.Vertical, - BorderStyle = LineStyle.Rounded }; - vBar.Add (shortcut1, shortcut2); + bar.Border.Thickness = new (1); + ConfigureMenu (bar); - menuLikeExamples.Add (vBar); + menuLikeExamples.Add (bar); - // BUGBUG: This should not be needed - menuLikeExamples.LayoutSubviews (); + label = new Label () + { + Title = "Menu:", + X = Pos.Right(bar) + 1, + Y = Pos.Top (label), + }; + menuLikeExamples.Add (label); - // SetupMenuBar (); - //SetupContentMenu (); + bar = new Menuv2 + { + Id = "menu", + X = Pos.Left (label), + Y = Pos.Bottom (label), + }; + ConfigureMenu (bar); + + menuLikeExamples.Add (bar); FrameView statusBarLikeExamples = new () { @@ -140,7 +145,7 @@ public class Bars : Scenario X = 0, Y = Pos.AnchorEnd (), Width = Dim.Width (menuLikeExamples), - Height = 10, + Height = Dim.Percent (33), }; Application.Top.Add (statusBarLikeExamples); @@ -148,7 +153,7 @@ public class Bars : Scenario { Title = " Bar:", X = 0, - Y = Pos.AnchorEnd () - 6 + Y = 0, }; statusBarLikeExamples.Add (label); bar = new Bar @@ -166,7 +171,7 @@ public class Bars : Scenario { Title = "StatusBar:", X = 0, - Y = Pos.AnchorEnd () - 3 + Y = Pos.Bottom (bar) + 1, }; statusBarLikeExamples.Add (label); bar = new StatusBar () @@ -348,22 +353,58 @@ public class Bars : Scenario var fileMenuBarItem = new Shortcut { Title = "_File", + HelpText = "File Menu", + Key = Key.D0.WithAlt, }; - fileMenuBarItem.KeyView.Visible = false; var editMenuBarItem = new Shortcut { Title = "_Edit", + HelpText = "Edit Menu", + Key = Key.D1.WithAlt }; - bar.Add (fileMenuBarItem, editMenuBarItem); + var helpMenuBarItem = new Shortcut + { + Title = "_Help", + HelpText = "Halp Menu", + Key = Key.D2.WithAlt + }; + + bar.Add (fileMenuBarItem, editMenuBarItem, helpMenuBarItem); + } + + private void ConfigureMenu (Bar bar) + { + + var shortcut1 = new Shortcut + { + Title = "Z_igzag", + Key = Key.I.WithCtrl, + Text = "Gonna zig zag", + }; + + var shortcut2 = new Shortcut + { + Title = "Za_G", + Text = "Gonna zag", + Key = Key.G.WithAlt, + }; + + var shortcut3 = new Shortcut + { + Title = "_Three", + Text = "The 3rd item", + Key = Key.D3.WithAlt, + }; + + bar.Add (shortcut1, shortcut2, shortcut3); } private void ConfigStatusBar (Bar bar) { var shortcut = new Shortcut { - Height = Dim.Auto (DimAutoStyle.Content, 3), Text = "Quit", Title = "Q_uit", Key = Key.Z.WithCtrl,