diff --git a/Terminal.Gui/View/ViewAdornments.cs b/Terminal.Gui/View/ViewAdornments.cs index 0ebf5499f..bc2a93468 100644 --- a/Terminal.Gui/View/ViewAdornments.cs +++ b/Terminal.Gui/View/ViewAdornments.cs @@ -1,4 +1,6 @@ -namespace Terminal.Gui; +using System.ComponentModel; + +namespace Terminal.Gui; public partial class View { @@ -95,29 +97,74 @@ public partial class View get => Border?.LineStyle ?? LineStyle.Single; set { - if (Border is null) - { - return; - } + StateEventArgs e = new (Border?.LineStyle ?? LineStyle.None, value); + OnBorderStyleChanging (e); - if (value != LineStyle.None) - { - if (Border.Thickness == Thickness.Empty) - { - Border.Thickness = new (1); - } - } - else - { - Border.Thickness = new (0); - } - - Border.LineStyle = value; - LayoutAdornments (); - SetNeedsLayout (); } } + /// + /// Called when the is changing. Invokes , which allows the event to be cancelled. + /// + /// + /// Override to prevent the from changing. Set to `true` to cancel the event. + /// + /// + protected void OnBorderStyleChanging (StateEventArgs e) + { + if (Border is null) + { + return; + } + + BorderStyleChanging?.Invoke (this, e); + if (e.Cancel) + { + return; + } + + SetBorderStyle (e.NewValue); + LayoutAdornments (); + SetNeedsLayout (); + + return; + } + + /// + /// Sets the of the view to the specified value. + /// + /// + /// + /// is a helper for manipulating the view's . Setting this property to any value other + /// than is equivalent to setting 's + /// to `1` and to the value. + /// + /// + /// Setting this property to is equivalent to setting 's + /// to `0` and to . + /// + /// For more advanced customization of the view's border, manipulate see directly. + /// + /// + public virtual void SetBorderStyle (LineStyle value) + { + if (value != LineStyle.None) + { + if (Border.Thickness == Thickness.Empty) + { + Border.Thickness = new (1); + } + } + else + { + Border.Thickness = new (0); + } + + Border.LineStyle = value; + } + + public event EventHandler> BorderStyleChanging; + /// /// The inside of the view that offsets the /// from the . diff --git a/Terminal.Gui/View/ViewDrawing.cs b/Terminal.Gui/View/ViewDrawing.cs index 74beffd3f..604b7d51a 100644 --- a/Terminal.Gui/View/ViewDrawing.cs +++ b/Terminal.Gui/View/ViewDrawing.cs @@ -640,17 +640,17 @@ public partial class View { SubViewNeedsDisplay = true; + if (this is Adornment adornment) + { + adornment.Parent?.SetSubViewNeedsDisplay (); + } + if (SuperView is { SubViewNeedsDisplay: false }) { SuperView.SetSubViewNeedsDisplay (); return; } - - if (this is Adornment adornment) - { - adornment.Parent?.SetSubViewNeedsDisplay (); - } } /// Clears and . diff --git a/Terminal.Gui/Views/Bar.cs b/Terminal.Gui/Views/Bar.cs index 251261993..4edeb57f9 100644 --- a/Terminal.Gui/Views/Bar.cs +++ b/Terminal.Gui/Views/Bar.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Microsoft.CodeAnalysis; namespace Terminal.Gui; @@ -8,12 +9,33 @@ namespace Terminal.Gui; /// /// /// -public class Bar : View +public class Bar : Toplevel { /// public Bar () { - SetInitialProperties (); + CanFocus = true; + + Width = Dim.Auto (); + Height = Dim.Auto (); + + LayoutStarted += Bar_LayoutStarted; + + Initialized += Bar_Initialized; + + } + + private void Bar_Initialized (object sender, EventArgs e) + { + ColorScheme = Colors.ColorSchemes ["Menu"]; + AdjustSubviewBorders(); + } + + /// + public override void SetBorderStyle (LineStyle value) + { + // The default changes the thickness. We don't want that. We just set the style. + Border.LineStyle = value; } /// @@ -31,46 +53,59 @@ public class Bar : View //view.AutoSize = true; } - //if (StatusBarStyle) - //{ - // // Light up right border - // view.BorderStyle = LineStyle.Single; - // view.Border.Thickness = new Thickness (0, 0, 1, 0); - //} - - //if (view is not Shortcut) - //{ - // if (StatusBarStyle) - // { - // view.Padding.Thickness = new Thickness (0, 0, 1, 0); - // } - - // view.Margin.Thickness = new Thickness (1, 0, 0, 0); - //} - - //view.ColorScheme = ColorScheme; - - // Add any HotKey keybindings to our bindings - //IEnumerable> bindings = view.KeyBindings.Bindings.Where (b => b.Value.Scope == KeyBindingScope.HotKey); - - //foreach (KeyValuePair binding in bindings) - //{ - // AddCommand ( - // binding.Value.Commands [0], - // () => - // { - // if (view is Shortcut shortcut) - // { - // return shortcut.CommandView.InvokeCommands (binding.Value.Commands); - // } - - // return false; - // }); - // KeyBindings.Add (binding.Key, binding.Value); - //} - - base.Add (view); + AdjustSubviewBorders (); + + } + + /// + public override void Remove (View view) + { + base.Remove (view); + AdjustSubviewBorders (); + } + + private void AdjustSubviewBorders () + { + for (var index = 0; index < Subviews.Count; index++) + { + View barItem = Subviews [index]; + + barItem.Border.LineStyle = BorderStyle; + barItem.SuperViewRendersLineCanvas = true; + barItem.ColorScheme = ColorScheme; + + + if (!barItem.Visible) + { + continue; + } + + if (StatusBarStyle) + { + if (index == 0) + { + barItem.Border.Thickness = new Thickness (0, 0, 1, 0); + } + + if (index == Subviews.Count - 1) + { + barItem.Border.Thickness = new Thickness (0, 0, 0, 0); + } + } + else + { + if (index == 0) + { + barItem.Border.Thickness = new Thickness (1, 1, 1, 0); + } + + if (index == Subviews.Count - 1) + { + barItem.Border.Thickness = new Thickness (1, 0, 1, 1); + } + } + } } private void Bar_LayoutStarted (object sender, LayoutEventArgs e) @@ -89,7 +124,15 @@ public class Bar : View continue; } - barItem.BorderStyle = LineStyle.Dashed; + if (StatusBarStyle) + { + barItem.BorderStyle = LineStyle.Dashed; + } + else + { + barItem.BorderStyle = LineStyle.None; + } + if (index == Subviews.Count - 1) { barItem.Border.Thickness = new Thickness (0, 0, 0, 0); @@ -99,7 +142,7 @@ public class Bar : View barItem.Border.Thickness = new Thickness (0, 0, 1, 0); } - barItem.X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast); + barItem.X = Pos.Align (Alignment.Start, StatusBarStyle ? AlignmentModes.IgnoreFirstOrLast : 0); barItem.Y = Pos.Center (); prevBarItem = barItem; } @@ -126,6 +169,7 @@ public class Bar : View // Set the overall size of the Bar and arrange the views vertically var maxBarItemWidth = 0; + var totalHeight = 0; for (var index = 0; index < Subviews.Count; index++) { @@ -148,7 +192,7 @@ public class Bar : View else { // Align the view to the bottom of the previous view - barItem.Y = index; + barItem.Y = Pos.Bottom(prevBarItem); } prevBarItem = barItem; @@ -163,6 +207,7 @@ public class Bar : View } barItem.X = 0; + totalHeight += barItem.Frame.Height; } foreach (Shortcut shortcut in shortcuts) @@ -170,20 +215,11 @@ public class Bar : View shortcut.Width = maxBarItemWidth; } - Height = Subviews.Count; + Height = Dim.Auto (DimAutoStyle.Content, minimumContentDim: totalHeight); break; } } - private void SetInitialProperties () - { - ColorScheme = Colors.ColorSchemes ["Menu"]; - CanFocus = true; - Width = Dim.Auto (); - Height = Dim.Auto (); - - LayoutStarted += Bar_LayoutStarted; - } } diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs index 1dfabeb86..e4484d128 100644 --- a/Terminal.Gui/Views/Shortcut.cs +++ b/Terminal.Gui/Views/Shortcut.cs @@ -45,8 +45,8 @@ public class Shortcut : View public Shortcut () { Id = "_shortcut"; - HighlightStyle = HighlightStyle.Pressed; - Highlight += Shortcut_Highlight; + //HighlightStyle = HighlightStyle.Pressed; + //Highlight += Shortcut_Highlight; CanFocus = true; Width = GetWidthDimAuto (); Height = Dim.Auto (DimAutoStyle.Content, 1); @@ -80,6 +80,7 @@ public class Shortcut : View KeyView.MouseClick += Shortcut_MouseClick; LayoutStarted += OnLayoutStarted; + DrawContent += Shortcut_DrawContent; Initialized += OnInitialized; @@ -98,17 +99,7 @@ public class Shortcut : View _minimumDimAutoWidth = Frame.Width; Width = savedDim; - // Set KeyView's colors to show "hot" - if (ColorScheme != null) - { - var cs = new ColorScheme (ColorScheme) - { - Normal = ColorScheme.HotNormal, - HotNormal = ColorScheme.Normal - }; - - KeyView.ColorScheme = cs; - } + //SetColorScheme (); } // Helper to set Width consistently @@ -119,6 +110,11 @@ public class Shortcut : View } } + private void Shortcut_DrawContent (object sender, DrawEventArgs e) + { + //SetColorScheme(); + } + /// /// Gets or sets the for this . The default is @@ -139,12 +135,12 @@ public class Shortcut : View Add (CommandView); } - if (!string.IsNullOrEmpty (HelpView.Text)) + if (HelpView.Visible && !string.IsNullOrEmpty (HelpView.Text)) { Add (HelpView); } - if (Key != Key.Empty) + if (KeyView.Visible && Key != Key.Empty) { Add (KeyView); } @@ -273,8 +269,6 @@ public class Shortcut : View { CommandView.InvokeCommand (Command.Accept); e.Handled = true; - - return; } if (!e.Handled) @@ -568,7 +562,7 @@ public class Shortcut : View private void SetKeyViewDefaultLayout () { - KeyView.Margin.Thickness = GetMarginThickness(); + KeyView.Margin.Thickness = GetMarginThickness (); KeyView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast); //KeyView.Y = Pos.Center (); KeyView.Width = Dim.Auto (DimAutoStyle.Text, Dim.Func (GetMinimumKeyViewSize)); @@ -645,50 +639,69 @@ public class Shortcut : View /// public override ColorScheme ColorScheme { - get - { - if (base.ColorScheme == null) - { - return SuperView?.ColorScheme ?? base.ColorScheme; - } - - return base.ColorScheme; - } + get => base.ColorScheme; set { base.ColorScheme = value; - - if (CommandView.CanFocus) - { - CommandView.ColorScheme = SuperView?.ColorScheme ?? ColorScheme; - } - - if (ColorScheme != null) - { - var cs = new ColorScheme (ColorScheme) - { - Normal = ColorScheme.HotNormal, - HotNormal = ColorScheme.Normal - }; - KeyView.ColorScheme = cs; - } - - Border.ColorScheme = SuperView?.ColorScheme ?? ColorScheme; + SetColorScheme (); } } + public void SetColorScheme () + { + // Border should match superview. + Border.ColorScheme = SuperView?.ColorScheme; + + if (HasFocus) + { + // When we have focus, we invert the SuperView's colors + base.ColorScheme = new (base.ColorScheme) + { + Normal = base.ColorScheme.Focus, + HotNormal = base.ColorScheme.HotFocus, + HotFocus = base.ColorScheme.HotNormal, + Focus = base.ColorScheme.Normal + }; + } + else + { + base.ColorScheme = SuperView?.ColorScheme; + } + + //// If the command view is focusable, invert the focus colors + if (CommandView.CanFocus) + { + ColorScheme commandViewCS = new (base.ColorScheme) + { + Normal = base.ColorScheme.Focus, + HotNormal = base.ColorScheme.HotFocus, + HotFocus = base.ColorScheme.HotNormal, + Focus = base.ColorScheme.Normal + }; + CommandView.ColorScheme = commandViewCS; + } + else + { + CommandView.ColorScheme = base.ColorScheme; + } + + //HelpView.ColorScheme = base.ColorScheme; + + //// Set KeyView's colors to show "hot" + //var cs = new ColorScheme (ColorScheme) + //{ + // Normal = base.ColorScheme.HotNormal, + // HotNormal = base.ColorScheme.Normal + //}; + + //KeyView.ColorScheme = cs; + + } + /// public override bool OnEnter (View view) { - if (SuperView is { }) - { - ColorScheme = new (SuperView?.ColorScheme) - { - Normal = SuperView.ColorScheme.Focus, - HotNormal = SuperView.ColorScheme.HotFocus - }; - } - + SetColorScheme (); return base.OnEnter (view); } @@ -696,8 +709,8 @@ public class Shortcut : View public override bool OnLeave (View view) { // Reset the color scheme (to SuperView). - ColorScheme = null; - + //ColorScheme = null; + SetColorScheme (); return base.OnLeave (view); } diff --git a/Terminal.Gui/Views/Slider.cs b/Terminal.Gui/Views/Slider.cs index eefc202d7..076a2adce 100644 --- a/Terminal.Gui/Views/Slider.cs +++ b/Terminal.Gui/Views/Slider.cs @@ -1377,7 +1377,8 @@ public class Slider : View SetNeedsDisplay (); - return true; + mouseEvent.Handled = true; + return OnMouseClick (new (mouseEvent)); } return false; diff --git a/UICatalog/Scenarios/Bars.cs b/UICatalog/Scenarios/Bars.cs index 441e83a5a..0fcdf7038 100644 --- a/UICatalog/Scenarios/Bars.cs +++ b/UICatalog/Scenarios/Bars.cs @@ -110,6 +110,7 @@ public class Bars : Scenario Y = 2, Orientation = Orientation.Vertical, StatusBarStyle = false, + BorderStyle = LineStyle.Rounded }; bar.Add (shortcut1, shortcut2); @@ -132,9 +133,9 @@ public class Bars : Scenario // BUGBUG: This should not be needed Application.Top.LayoutSubviews (); - //SetupMenuBar (); + // SetupMenuBar (); //SetupContentMenu (); - SetupStatusBar (); + // SetupStatusBar (); foreach (Bar barView in Application.Top.Subviews.Where (b => b is Bar)!) { @@ -298,103 +299,111 @@ public class Bars : Scenario ((View)(sender)).LayoutSubviews (); } - //private void SetupMenuBar () - //{ - // var menuBar = new Bar - // { - // Id = "menuBar", + private void SetupMenuBar () + { + var menuBar = new Bar + { + Id = "menuBar", + Width = Dim.Fill (), + Height = 1,//Dim.Auto (DimAutoStyle.Content), + Orientation = Orientation.Horizontal, + StatusBarStyle = false, + }; - // X = 0, - // Y = 0, - // Width = Dim.Fill (), - // Height = Dim.Auto (DimAutoStyle.Content), - // StatusBarStyle = true - // }; + var fileMenuBarItem = new Shortcut + { + Title = "_File", + KeyBindingScope = KeyBindingScope.Application, + Key = Key.F.WithAlt, + }; + fileMenuBarItem.KeyView.Visible = false; + + var editMenuBarItem = new Shortcut + { + Title = "_Edit", - // var fileMenu = new Shortcut - // { - // Title = "_File", - // Key = Key.F.WithAlt, - // KeyBindingScope = KeyBindingScope.HotKey, - // Command = Command.Accept, - // }; - // fileMenu.HelpView.Visible = false; - // fileMenu.KeyView.Visible = false; + KeyBindingScope = KeyBindingScope.HotKey, + }; - // fileMenu.Accept += (s, e) => - // { - // fileMenu.SetFocus (); + editMenuBarItem.Accept += (s, e) => { }; + //editMenu.HelpView.Visible = false; + //editMenu.KeyView.Visible = false; - // if (s is View view) - // { - // var menu = new Bar - // { - // X = view.Frame.X + 1, - // Y = view.Frame.Y + 1, - // ColorScheme = view.ColorScheme, - // Orientation = Orientation.Vertical, - // StatusBarStyle = false, - // BorderStyle = LineStyle.Dotted, - // Width = Dim.Auto (DimAutoStyle.Content), - // Height = Dim.Auto (DimAutoStyle.Content), - // }; + menuBar.Add (fileMenuBarItem, editMenuBarItem); + menuBar.Initialized += Menu_Initialized; + Application.Top.Add (menuBar); - // menu.KeyBindings.Add (Key.Esc, Command.QuitToplevel); + var fileMenu = new Bar + { + X = 1, + Y = 1, + Orientation = Orientation.Vertical, + StatusBarStyle = false, + Modal = true, + Visible = false, + }; - // var newMenu = new Shortcut - // { - // Title = "_New...", - // Text = "Create a new file", - // Key = Key.N.WithCtrl - // }; + 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 open = new Shortcut - // { - // Title = "_Open...", - // Text = "Show the File Open Dialog", - // Key = Key.O.WithCtrl - // }; + var openShortcut = new Shortcut + { + Title = "_Open...", + Text = "Show the File Open Dialog", + Key = Key.O.WithCtrl + }; - // var save = new Shortcut - // { - // Title = "_Save...", - // Text = "Save", - // Key = Key.S.WithCtrl - // }; + var saveShortcut = new Shortcut + { + Title = "_Save...", + Text = "Save", + Key = Key.S.WithCtrl, + Enabled = false + }; - // menu.Add (newMenu, open, save); + var exitShortcut = new Shortcut + { + Title = "E_xit", + Text = "Exit", + Key = Key.X.WithCtrl, + }; + exitShortcut.Border.Thickness = new Thickness (0, 1, 0, 1); - // // BUGBUG: this is all bad - // menu.Initialized += Menu_Initialized; - // open.Initialized += Menu_Initialized; - // save.Initialized += Menu_Initialized; - // newMenu.Initialized += Menu_Initialized; + fileMenu.Add (newShortcut, openShortcut, saveShortcut, exitShortcut); - // Application.Run (menu); - // menu.Dispose (); - // Application.Refresh (); - // } - // }; + View prevFocus = null; + fileMenuBarItem.Accept += (s, e) => + { + if (fileMenu.Visible) + { + fileMenu.RequestStop (); + prevFocus?.SetFocus (); + return; + } - // var editMenu = new Shortcut - // { - // Title = "_Edit", + //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; + }; - // //Key = Key.E.WithAlt, - // KeyBindingScope = KeyBindingScope.HotKey, - // Command = Command.Accept - // }; + Application.Top.Closed += (s, e) => + { + fileMenu.Dispose (); + }; - // editMenu.Accept += (s, e) => { }; - // editMenu.HelpView.Visible = false; - // editMenu.KeyView.Visible = false; - - // menuBar.Add (fileMenu, editMenu); - - // menuBar.Initialized += Menu_Initialized; - - // Application.Top.Add (menuBar); - //} + } private void SetupStatusBar () { diff --git a/UICatalog/Scenarios/Shortcuts.cs b/UICatalog/Scenarios/Shortcuts.cs index c2411a379..2c63d3d8c 100644 --- a/UICatalog/Scenarios/Shortcuts.cs +++ b/UICatalog/Scenarios/Shortcuts.cs @@ -1,6 +1,7 @@ using System; using System.Collections.ObjectModel; using System.Linq; +using System.Threading.Tasks; using System.Timers; using Terminal.Gui; @@ -81,14 +82,14 @@ public class Shortcuts : Scenario vShortcut2.Accept += (o, args) => { // Cycle to next item. If at end, set 0 - if (((RadioGroup)vShortcut2.CommandView).SelectedItem < ((RadioGroup)vShortcut2.CommandView).RadioLabels.Length - 1) - { - ((RadioGroup)vShortcut2.CommandView).SelectedItem++; - } - else - { - ((RadioGroup)vShortcut2.CommandView).SelectedItem = 0; - } + //if (((RadioGroup)vShortcut2.CommandView).SelectedItem < ((RadioGroup)vShortcut2.CommandView).RadioLabels.Length - 1) + //{ + // ((RadioGroup)vShortcut2.CommandView).SelectedItem++; + //} + //else + //{ + // ((RadioGroup)vShortcut2.CommandView).SelectedItem = 0; + //} }; vShortcut2.Border.Thickness = new (1, 1, 1, 1); Application.Top.Add (vShortcut2); @@ -99,7 +100,7 @@ public class Shortcuts : Scenario X = 0, Y = Pos.Bottom (vShortcut2), CommandView = new CheckBox { Text = "_Align" }, - Key = Key.F3, + Key = Key.F5.WithCtrl.WithAlt.WithShift, HelpText = "Width is Fill", Width = Dim.Fill () - Dim.Width (eventLog), KeyBindingScope = KeyBindingScope.HotKey, @@ -161,7 +162,7 @@ public class Shortcuts : Scenario Y = Pos.Bottom (vShortcut4), Width = Dim.Width (vShortcut4), - Key = Key.F5.WithCtrl.WithAlt.WithShift, + Key = Key.F4, HelpText = "CommandView.CanFocus", KeyBindingScope = KeyBindingScope.HotKey, BorderStyle = LineStyle.Rounded, @@ -178,8 +179,11 @@ public class Shortcuts : Scenario foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!) { - peer.CanFocus = e.NewValue == true; - peer.CommandView.CanFocus = e.NewValue == true; + if (peer.CanFocus) + { + peer.CommandView.CanFocus = e.NewValue == true; + peer.SetColorScheme (); + } } } }; @@ -224,13 +228,14 @@ public class Shortcuts : Scenario Title = "_No Key", HelpText = "Keyless", - BorderStyle = LineStyle.Rounded + BorderStyle = LineStyle.Rounded, }; vShortcut6.Border.Thickness = new (1, 1, 1, 1); Application.Top.Add (vShortcut6); + vShortcut6.SetFocus (); - ((CheckBox)vShortcut3.CommandView).OnToggled(); + ((CheckBox)vShortcut3.CommandView).OnToggled (); // Horizontal var hShortcut1 = new Shortcut @@ -303,7 +308,7 @@ public class Shortcuts : Scenario var hShortcutBG = new Shortcut { - X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1)-1, + X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1) - 1, Y = Pos.Top (hShortcut2), Key = Key.F9, HelpText = "BG Color",