Tig 9 месяцев назад
Родитель
Сommit
4d4dbbf8b9

+ 5 - 4
Terminal.Gui/Drawing/Thickness.cs

@@ -88,9 +88,10 @@ public record struct Thickness
     ///     Thickness.
     /// </remarks>
     /// <param name="rect">The location and size of the rectangle that bounds the thickness rectangle, in screen coordinates.</param>
+    /// <param name="diagnosticFlags"></param>
     /// <param name="label">The diagnostics label to draw on the bottom of the <see cref="Bottom"/>.</param>
     /// <returns>The inner rectangle remaining to be drawn.</returns>
-    public Rectangle Draw (Rectangle rect, string label = null)
+    public Rectangle Draw (Rectangle rect, ViewDiagnosticFlags diagnosticFlags = ViewDiagnosticFlags.Off, string label = null)
     {
         if (rect.Size.Width < 1 || rect.Size.Height < 1)
         {
@@ -103,7 +104,7 @@ public record struct Thickness
         Rune topChar = clearChar;
         Rune bottomChar = clearChar;
 
-        if (View.Diagnostics.HasFlag (ViewDiagnosticFlags.Padding))
+        if (diagnosticFlags.HasFlag (ViewDiagnosticFlags.Padding))
         {
             leftChar = (Rune)'L';
             rightChar = (Rune)'R';
@@ -155,7 +156,7 @@ public record struct Thickness
                                         );
         }
 
-        if (View.Diagnostics.HasFlag (ViewDiagnosticFlags.Ruler))
+        if (diagnosticFlags.HasFlag (ViewDiagnosticFlags.Ruler))
         {
             // PERF: This can almost certainly be simplified down to a single point offset and fewer calls to Draw
             // Top
@@ -187,7 +188,7 @@ public record struct Thickness
             }
         }
 
-        if (View.Diagnostics.HasFlag (ViewDiagnosticFlags.Padding))
+        if (diagnosticFlags.HasFlag (ViewDiagnosticFlags.Padding))
         {
             // Draw the diagnostics label on the bottom
             string text = label is null ? string.Empty : $"{label} {this}";

+ 7 - 1
Terminal.Gui/View/Adornment/Adornment.cs

@@ -42,6 +42,11 @@ public class Adornment : View
 
     #region Thickness
 
+    /// <summary>
+    /// 
+    /// </summary>
+    public ViewDiagnosticFlags Diagnostics { get; set; } = View.Diagnostics;
+
     private Thickness _thickness = Thickness.Empty;
 
     /// <summary>Defines the rectangle that the <see cref="Adornment"/> will use to draw its content.</summary>
@@ -51,6 +56,7 @@ public class Adornment : View
         set
         {
             Thickness current = _thickness;
+
             _thickness = value;
 
             if (current != _thickness)
@@ -154,7 +160,7 @@ public class Adornment : View
         Driver?.SetAttribute (normalAttr);
 
         // This just draws/clears the thickness, not the insides.
-        Thickness.Draw (screen, ToString ());
+        Thickness.Draw (screen, Diagnostics, ToString ());
 
         if (!string.IsNullOrEmpty (TextFormatter.Text))
         {

+ 1 - 1
Terminal.Gui/View/Adornment/Margin.cs

@@ -86,7 +86,7 @@ public class Margin : Adornment
         }
 
         // This just draws/clears the thickness, not the insides.
-        Thickness.Draw (screen, ToString ());
+        Thickness.Draw (screen, Diagnostics, ToString ());
 
         if (Subviews.Count > 0)
         {

+ 2 - 1
Terminal.Gui/View/Layout/PosAlign.cs

@@ -1,6 +1,7 @@
 #nullable enable
 
 using System.ComponentModel;
+using System.Text.RegularExpressions;
 
 namespace Terminal.Gui;
 
@@ -123,7 +124,7 @@ public record PosAlign : Pos
         }
         else
         {
-            groupViews = us.SuperView!.Subviews;
+            groupViews = us.SuperView!.Subviews.Where (v => HasGroupId (v, dimension, GroupId)).ToList ();
         }
 
         AlignAndUpdateGroup (GroupId, groupViews, dimension, superviewDimension);

+ 1 - 1
Terminal.Gui/View/View.Adornments.cs

@@ -142,7 +142,7 @@ public partial class View // Adornments
             LineStyle old = Border?.LineStyle ?? LineStyle.None;
             CancelEventArgs<LineStyle> e = new (ref old, ref value);
 
-            if (OnBorderStyleChanging (e)|| e.Cancel)
+            if (OnBorderStyleChanging (e) || e.Cancel)
             {
                 return;
             }

+ 5 - 1
Terminal.Gui/View/View.Layout.cs

@@ -352,6 +352,7 @@ public partial class View // Layout APIs
             {
                 // Implicit layout is ok here because all Pos/Dim are Absolute values.
                 Layout ();
+                SetLayoutNeeded ();
             }
         }
     }
@@ -406,6 +407,7 @@ public partial class View // Layout APIs
             {
                 // Implicit layout is ok here because all Pos/Dim are Absolute values.
                 Layout ();
+                SetLayoutNeeded ();
             }
         }
     }
@@ -463,6 +465,7 @@ public partial class View // Layout APIs
             {
                 // Implicit layout is ok here because all Pos/Dim are Absolute values.
                 Layout ();
+                SetLayoutNeeded ();
             }
         }
     }
@@ -521,6 +524,7 @@ public partial class View // Layout APIs
             {
                 // Implicit layout is ok here because all Pos/Dim are Absolute values.
                 Layout ();
+                SetLayoutNeeded ();
             }
         }
     }
@@ -554,7 +558,7 @@ public partial class View // Layout APIs
             {
                 LayoutSubviews ();
 
-                Debug.Assert(!NeedsLayout);
+               // Debug.Assert(!NeedsLayout);
                 return true;
             }
 

+ 55 - 42
Terminal.Gui/Views/Bar.cs

@@ -31,7 +31,7 @@ public class Bar : View, IOrientation, IDesignable
         _orientationHelper.OrientationChanging += (sender, e) => OrientationChanging?.Invoke (this, e);
         _orientationHelper.OrientationChanged += (sender, e) => OrientationChanged?.Invoke (this, e);
 
-       // Initialized += Bar_Initialized;
+        // Initialized += Bar_Initialized;
         MouseEvent += OnMouseEvent;
 
         if (shortcuts is null)
@@ -120,7 +120,8 @@ public class Bar : View, IOrientation, IDesignable
     /// <param name="newOrientation"></param>
     public void OnOrientationChanged (Orientation newOrientation)
     {
-        LayoutBarItems (SuperView?.GetContentSize() ?? Application.Screen.Size);
+        // BUGBUG: this should not be SuperView.GetContentSize
+        LayoutBarItems (SuperView?.GetContentSize () ?? Application.Screen.Size);
     }
     #endregion
 
@@ -136,6 +137,7 @@ public class Bar : View, IOrientation, IDesignable
         set
         {
             _alignmentModes = value;
+            SetNeedsDisplay ();
             SetLayoutNeeded ();
         }
     }
@@ -164,6 +166,7 @@ public class Bar : View, IOrientation, IDesignable
         }
 
         SetNeedsDisplay ();
+        SetLayoutNeeded ();
     }
 
     // TODO: Move this to View
@@ -187,6 +190,7 @@ public class Bar : View, IOrientation, IDesignable
         {
             Remove (toRemove);
             SetNeedsDisplay ();
+            SetLayoutNeeded ();
         }
 
         return toRemove as Shortcut;
@@ -221,63 +225,72 @@ public class Bar : View, IOrientation, IDesignable
                 break;
 
             case Orientation.Vertical:
-                // Set the overall size of the Bar and arrange the views vertically
-
-                var minKeyWidth = 0;
-
-                List<Shortcut> shortcuts = Subviews.Where (s => s is Shortcut && s.Visible).Cast<Shortcut> ().ToList ();
-                foreach (Shortcut shortcut in shortcuts)
+                if (Width!.Has<DimAuto> (out _))
                 {
-                    // Let DimAuto 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;
+                    var minKeyWidth = 0;
 
-                for (var index = 0; index < Subviews.Count; index++)
-                {
-                    View barItem = Subviews [index];
-
-                    barItem.ColorScheme = ColorScheme;
+                    List<Shortcut> shortcuts = Subviews.Where (s => s is Shortcut && s.Visible).Cast<Shortcut> ().ToList ();
 
-                    if (!barItem.Visible)
+                    foreach (Shortcut shortcut in shortcuts)
                     {
-                        continue;
+                        // Get the largest width of all KeyView's
+                        minKeyWidth = int.Max (minKeyWidth, shortcut.KeyView.Text.GetColumns ());
                     }
 
-                    if (barItem is Shortcut scBarItem)
+                    var _maxBarItemWidth = 0;
+
+                    for (var index = 0; index < Subviews.Count; index++)
                     {
-                        scBarItem.MinimumKeyTextSize = minKeyWidth;
+                        View barItem = Subviews [index];
+
+                        barItem.X = 0;
+
+                        barItem.ColorScheme = ColorScheme;
+
+                        if (!barItem.Visible)
+                        {
+                            continue;
+                        }
+
+                        if (barItem is Shortcut scBarItem)
+                        {
+                            scBarItem.MinimumKeyTextSize = minKeyWidth;
+                            scBarItem.Width = scBarItem.GetWidthDimAuto ();
+                            barItem.Layout (Application.Screen.Size);
+                            _maxBarItemWidth = Math.Max (_maxBarItemWidth, barItem.Frame.Width);
+                        }
+
+                        if (prevBarItem == null)
+                        {
+                            // TODO: Just use Pos.Align!
+                            barItem.Y = 0;
+                        }
+                        else
+                        {
+                            // TODO: Just use Pos.Align!
+                            // Align the view to the bottom of the previous view
+                            barItem.Y = Pos.Bottom (prevBarItem);
+                        }
+
+                        prevBarItem = barItem;
 
-                        _maxBarItemWidth = Math.Max (_maxBarItemWidth, scBarItem.Frame.Width);
                     }
 
-                    if (prevBarItem == null)
-                    {
-                        barItem.Y = 0;
-                    }
-                    else
+                    foreach (var subView in Subviews)
                     {
-                        // Align the view to the bottom of the previous view
-                        barItem.Y = Pos.Bottom (prevBarItem);
+                        subView.Width = Dim.Auto (DimAutoStyle.Auto, minimumContentDim: _maxBarItemWidth);
                     }
-
-                    prevBarItem = barItem;
-
-                    barItem.X = 0;
-                    totalHeight += barItem.Frame.Height;
                 }
-
-
-                foreach (View barItem in Subviews)
+                else
                 {
-                    barItem.Width = _maxBarItemWidth;
+                    foreach (var subView in Subviews)
+                    {
+                        subView.Width = Dim.Fill();
+                    }
                 }
 
-                Height = Dim.Auto (DimAutoStyle.Content, totalHeight);
-
                 break;
         }
     }

+ 37 - 20
Terminal.Gui/Views/ColorPicker.16.cs

@@ -67,8 +67,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the next row.</summary>
     /// <returns></returns>
-    public virtual bool MoveDown ()
+    private bool MoveDown (CommandContext ctx)
     {
+        if (RaiseSelecting (ctx) == true)
+        {
+            return true;
+        }
         if (Cursor.Y < _rows - 1)
         {
             SelectedColor += _cols;
@@ -79,8 +83,13 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the previous column.</summary>
     /// <returns></returns>
-    public virtual bool MoveLeft ()
+    private bool MoveLeft (CommandContext ctx)
     {
+        if (RaiseSelecting (ctx) == true)
+        {
+            return true;
+        }
+
         if (Cursor.X > 0)
         {
             SelectedColor--;
@@ -91,8 +100,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the next column.</summary>
     /// <returns></returns>
-    public virtual bool MoveRight ()
+    private bool MoveRight (CommandContext ctx)
     {
+        if (RaiseSelecting (ctx) == true)
+        {
+            return true;
+        }
         if (Cursor.X < _cols - 1)
         {
             SelectedColor++;
@@ -103,8 +116,12 @@ public class ColorPicker16 : View
 
     /// <summary>Moves the selected item index to the previous row.</summary>
     /// <returns></returns>
-    public virtual bool MoveUp ()
+    private bool MoveUp (CommandContext ctx)
     {
+        if (RaiseSelecting (ctx) == true)
+        {
+            return true;
+        }
         if (Cursor.Y > 0)
         {
             SelectedColor -= _cols;
@@ -164,13 +181,24 @@ public class ColorPicker16 : View
     /// <summary>Add the commands.</summary>
     private void AddCommands ()
     {
-        AddCommand (Command.Left, () => MoveLeft ());
-        AddCommand (Command.Right, () => MoveRight ());
-        AddCommand (Command.Up, () => MoveUp ());
-        AddCommand (Command.Down, () => MoveDown ());
+        AddCommand (Command.Left, (ctx) => MoveLeft (ctx));
+        AddCommand (Command.Right, (ctx) => MoveRight (ctx));
+        AddCommand (Command.Up, (ctx) => MoveUp (ctx));
+        AddCommand (Command.Down, (ctx) => MoveDown (ctx));
+
+        AddCommand (Command.Select, (ctx) =>
+                                    {
+                                        bool set = false;
+                                        if (ctx.Data is MouseEventArgs me)
+                                        {
+                                            Cursor = new (me.Position.X / _boxWidth, me.Position.Y / _boxHeight);
+                                            set = true;
+                                        }
+                                        return RaiseAccepting (ctx) == true || set;
+                                    });
     }
 
-    /// <summary>Add the KeyBindinds.</summary>
+    /// <summary>Add the KeyBindings.</summary>
     private void AddKeyBindings ()
     {
         KeyBindings.Add (Key.CursorLeft, Command.Left);
@@ -181,15 +209,6 @@ public class ColorPicker16 : View
 
     // TODO: Decouple Cursor from SelectedColor so that mouse press-and-hold can show the color under the cursor.
 
-    private void ColorPicker_MouseClick (object sender, MouseEventArgs me)
-    {
-        // if (CanFocus)
-        {
-            Cursor = new (me.Position.X / _boxWidth, me.Position.Y / _boxHeight);
-            SetFocus ();
-            me.Handled = true;
-        }
-    }
 
     /// <summary>Draw a box for one color.</summary>
     /// <param name="x">X location.</param>
@@ -265,7 +284,5 @@ public class ColorPicker16 : View
         Width = Dim.Auto (minimumContentDim: _boxWidth * _cols);
         Height = Dim.Auto (minimumContentDim: _boxHeight * _rows);
         SetContentSize (new (_boxWidth * _cols, _boxHeight * _rows));
-
-        MouseClick += ColorPicker_MouseClick;
     }
 }

+ 3 - 0
Terminal.Gui/Views/HexView.cs

@@ -198,6 +198,7 @@ public class HexView : View, IDesignable
                 Address = 0;
             }
 
+            SetLayoutNeeded ();
             SetNeedsDisplay ();
         }
     }
@@ -577,6 +578,8 @@ public class HexView : View, IDesignable
     /// </summary>
     protected void RaisePositionChanged ()
     {
+        SetNeedsDisplay ();
+
         HexViewEventArgs args = new (Address, Position, BytesPerLine);
         OnPositionChanged (args);
         PositionChanged?.Invoke (this, args);

+ 2 - 2
Terminal.Gui/Views/RadioGroup.cs

@@ -52,9 +52,9 @@ public class RadioGroup : View, IDesignable, IOrientation
         // Accept (Enter key) - Raise Accept event - DO NOT advance state
         AddCommand (Command.Accept, RaiseAccepting);
 
-        // Hotkey - ctx may indicate a radio item hotkey was pressed. Beahvior depends on HasFocus
+        // Hotkey - ctx may indicate a radio item hotkey was pressed. Behavior depends on HasFocus
         //          If HasFocus and it's this.HotKey invoke Select command - DO NOT raise Accept
-        //          If it's a radio item HotKey select that item and raise Seelcted event - DO NOT raise Accept
+        //          If it's a radio item HotKey select that item and raise Selected event - DO NOT raise Accept
         //          If nothing is selected, select first and raise Selected event - DO NOT raise Accept
         AddCommand (Command.HotKey,
                     ctx =>

+ 68 - 55
Terminal.Gui/Views/Shortcut.cs

@@ -96,6 +96,10 @@ public class Shortcut : View, IOrientation, IDesignable
 
         HighlightStyle = HighlightStyle.None;
         CanFocus = true;
+
+        SuperViewRendersLineCanvas = true;
+        Border.Settings &= ~BorderSettings.Title;
+
         Width = GetWidthDimAuto ();
         Height = Dim.Auto (DimAutoStyle.Content, 1);
 
@@ -111,8 +115,9 @@ public class Shortcut : View, IOrientation, IDesignable
         {
             Id = "CommandView",
             Width = Dim.Auto (),
-            Height = Dim.Auto (DimAutoStyle.Auto, 1)
+            Height = Dim.Fill()
         };
+        Title = commandText ?? string.Empty;
 
         HelpView.Id = "_helpView";
         HelpView.CanFocus = false;
@@ -120,36 +125,31 @@ public class Shortcut : View, IOrientation, IDesignable
 
         KeyView.Id = "_keyView";
         KeyView.CanFocus = false;
-
-        LayoutStarted += OnLayoutStarted;
-
         key ??= Key.Empty;
         Key = key;
-        Title = commandText ?? string.Empty;
+
         Action = action;
 
-        SuperViewRendersLineCanvas = true;
-        Border.Settings &= ~BorderSettings.Title;
+        LayoutStarted += OnLayoutStarted;
 
         ShowHide ();
     }
 
     // Helper to set Width consistently
-    private Dim GetWidthDimAuto ()
+    public Dim GetWidthDimAuto ()
     {
-        // TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
         return Dim.Auto (
                          DimAutoStyle.Content,
-                         Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width)),
-                         Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width)))!;
-    }
+                         minimumContentDim: Dim.Func (() => _minimumNaturalWidth ?? 0),
+                         maximumContentDim: Dim.Func (() => _minimumNaturalWidth ?? 0))!;
+}
 
     private AlignmentModes _alignmentModes = AlignmentModes.StartToEnd | AlignmentModes.IgnoreFirstOrLast;
 
     // This is used to calculate the minimum width of the Shortcut when Width is NOT Dim.Auto
     // It is calculated by setting Width to DimAuto temporarily and forcing layout.
     // Once Frame.Width gets below this value, LayoutStarted makes HelpView an KeyView smaller.
-    private int? _minimumNatrualWidth;
+    private int? _minimumNaturalWidth;
 
     /// <inheritdoc/>
     protected override bool OnHighlight (CancelEventArgs<HighlightStyle> args)
@@ -208,60 +208,48 @@ public class Shortcut : View, IOrientation, IDesignable
             SetKeyViewDefaultLayout ();
         }
 
-        // Force Width to DimAuto to calculate natural width and then set it back
-        Dim? savedDim = Width;
-        Width = GetWidthDimAuto ();
-        // Force a SRL)
+        SetColors ();
+    }
+
+    // Force Width to DimAuto to calculate natural width and then set it back
+    private void ForceCalculateNaturalWidth ()
+    {
+        // Get the natural size of each subview
         CommandView.SetRelativeLayout (Application.Screen.Size);
         HelpView.SetRelativeLayout (Application.Screen.Size);
         KeyView.SetRelativeLayout (Application.Screen.Size);
-        SetRelativeLayout (Application.Screen.Size);
-        _minimumNatrualWidth = Frame.Width;
-        Width = savedDim;
 
-        SetColors ();
+        _minimumNaturalWidth = PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width);
+
+        // Reset our relative layout
+        SetRelativeLayout (SuperView?.GetContentSize() ?? Application.Screen.Size);
     }
 
+    // TODO: Enable setting of the margin thickness
     private Thickness GetMarginThickness ()
     {
         return new (1, 0, 1, 0);
     }
 
-    private int _maxHelpWidth = 0;
     // When layout starts, we need to adjust the layout of the HelpView and KeyView
     private void OnLayoutStarted (object? sender, LayoutEventArgs e)
     {
+        ShowHide ();
+        ForceCalculateNaturalWidth ();
+
         if (Width is DimAuto widthAuto)
         {
-            _minimumNatrualWidth = Frame.Width;
-        }
+
+        } 
         else
         {
-            if (string.IsNullOrEmpty (HelpView.Text))
-            {
-                return;
-            }
-
-            int currentWidth = Frame.Width;
-
-            // Frame.Width is smaller than the natural width. Reduce width of HelpView first.
-            // Then KeyView.
-            // Don't ever reduce CommandView (it should spill).
-            // TODO: Add Unit tests for this.
-            int delta = _minimumNatrualWidth.Value - currentWidth;
-            _maxHelpWidth = int.Max (0, GetContentSize().Width - CommandView.Frame.Width - KeyView.Frame.Width);
+            // Frame.Width is smaller than the natural width. Reduce width of HelpView.
+            _maxHelpWidth = int.Max (0, GetContentSize ().Width - CommandView.Frame.Width - KeyView.Frame.Width);
             if (_maxHelpWidth < 3)
             {
                 Thickness t = GetMarginThickness ();
                 switch (_maxHelpWidth)
                 {
-                    case 2:
-
-                        // Scrunch just the right margin
-                        HelpView.Margin.Thickness = new (t.Right, t.Top, t.Left - 1, t.Bottom);
-
-                        break;
-
                     case 0:
                     case 1:
                         // Scrunch it by removing both margins
@@ -269,6 +257,12 @@ public class Shortcut : View, IOrientation, IDesignable
 
                         break;
 
+                    case 2:
+
+                        // Scrunch just the right margin
+                        HelpView.Margin.Thickness = new (t.Right, t.Top, t.Left - 1, t.Bottom);
+
+                        break;
                 }
             }
             else
@@ -276,7 +270,6 @@ public class Shortcut : View, IOrientation, IDesignable
                 // Reset to default
                 HelpView.Margin.Thickness = GetMarginThickness ();
             }
-            KeyView.SetLayoutNeeded();
         }
     }
 
@@ -472,7 +465,7 @@ public class Shortcut : View, IOrientation, IDesignable
             _commandView.Selecting += CommandViewOnSelecting;
             _commandView.Accepting += CommandViewOnAccepted;
 
-            ShowHide ();
+            //ShowHide ();
             UpdateKeyBindings (Key.Empty);
 
             return;
@@ -500,8 +493,11 @@ public class Shortcut : View, IOrientation, IDesignable
     {
         CommandView.Margin.Thickness = GetMarginThickness ();
         CommandView.X = Pos.Align (Alignment.End, AlignmentModes);
-        CommandView.Y = 0; //Pos.Center ();
-        HelpView.HighlightStyle = HighlightStyle.None;
+
+        CommandView.VerticalTextAlignment = Alignment.Center;
+        CommandView.TextAlignment = Alignment.Start;
+        CommandView.TextFormatter.WordWrap = false;
+        CommandView.HighlightStyle = HighlightStyle.None;
     }
 
     private void Shortcut_TitleChanged (object? sender, EventArgs<string> e)
@@ -516,6 +512,9 @@ public class Shortcut : View, IOrientation, IDesignable
 
     #region Help
 
+    // The maximum width of the HelpView. Calculated in OnLayoutStarted and used in HelpView.Width (Dim.Auto/Func).
+    private int _maxHelpWidth = 0;
+
     /// <summary>
     ///     The subview that displays the help text for the command. Internal for unit testing.
     /// </summary>
@@ -525,10 +524,9 @@ public class Shortcut : View, IOrientation, IDesignable
     {
         HelpView.Margin.Thickness = GetMarginThickness ();
         HelpView.X = Pos.Align (Alignment.End, AlignmentModes);
-        HelpView.Y = 0; //Pos.Center ();
         _maxHelpWidth = HelpView.Text.GetColumns ();
         HelpView.Width = Dim.Auto (DimAutoStyle.Text, maximumContentDim: Dim.Func ((() => _maxHelpWidth)));
-        HelpView.Height = CommandView?.Visible == true ? Dim.Height (CommandView) : 1;
+        HelpView.Height = Dim.Fill ();
 
         HelpView.Visible = true;
         HelpView.VerticalTextAlignment = Alignment.Center;
@@ -644,6 +642,8 @@ public class Shortcut : View, IOrientation, IDesignable
 
             _minimumKeyTextSize = value;
             SetKeyViewDefaultLayout ();
+
+            // TODO: Prob not needed
             CommandView.SetLayoutNeeded ();
             HelpView.SetLayoutNeeded ();
             KeyView.SetLayoutNeeded ();
@@ -656,9 +656,8 @@ public class Shortcut : View, IOrientation, IDesignable
     {
         KeyView.Margin.Thickness = GetMarginThickness ();
         KeyView.X = Pos.Align (Alignment.End, AlignmentModes);
-        KeyView.Y = 0;
         KeyView.Width = Dim.Auto (DimAutoStyle.Text, minimumContentDim: Dim.Func (() => MinimumKeyTextSize));
-        KeyView.Height = CommandView?.Visible == true ? Dim.Height (CommandView) : 1;
+        KeyView.Height = Dim.Fill ();
 
         KeyView.Visible = true;
 
@@ -706,11 +705,12 @@ public class Shortcut : View, IOrientation, IDesignable
         get => base.ColorScheme;
         set
         {
-            base.ColorScheme = value;
+            base.ColorScheme = _nonFocusColorScheme = value;
             SetColors ();
         }
     }
 
+    private ColorScheme? _nonFocusColorScheme;
     /// <summary>
     /// </summary>
     internal void SetColors (bool highlight = false)
@@ -718,11 +718,16 @@ public class Shortcut : View, IOrientation, IDesignable
         // Border should match superview.
         if (Border is { })
         {
-            Border.ColorScheme = SuperView?.ColorScheme;
+            // Border.ColorScheme = SuperView?.ColorScheme;
         }
 
         if (HasFocus || highlight)
         {
+            if (_nonFocusColorScheme is null)
+            {
+                _nonFocusColorScheme = base.ColorScheme;
+            }
+
             base.ColorScheme ??= new (Attribute.Default);
 
             // When we have focus, we invert the colors
@@ -736,7 +741,15 @@ public class Shortcut : View, IOrientation, IDesignable
         }
         else
         {
-            base.ColorScheme = SuperView?.ColorScheme ?? base.ColorScheme;
+            if (_nonFocusColorScheme is { })
+            {
+                base.ColorScheme = _nonFocusColorScheme;
+               //_nonFocusColorScheme = null;
+            }
+            else
+            {
+                base.ColorScheme = SuperView?.ColorScheme ?? base.ColorScheme;
+            }
         }
 
         // Set KeyView's colors to show "hot"

+ 4 - 2
UICatalog/Scenarios/AllViewsTester.cs

@@ -50,7 +50,6 @@ public class AllViewsTester : Scenario
     {
         // Don't create a sub-win (Scenario.Win); just use Application.Top
         Application.Init ();
-   //     ConfigurationManager.Apply ();
 
         var app = new Window
         {
@@ -315,8 +314,11 @@ public class AllViewsTester : Scenario
             Height = Dim.Fill (), // + 1 for status bar
             CanFocus = true,
             TabStop = TabBehavior.TabGroup,
-            ColorScheme = Colors.ColorSchemes ["Dialog"]
+            ColorScheme = Colors.ColorSchemes ["Base"]
         };
+        _hostPane.Padding.Thickness = new (1);
+        _hostPane.Padding.Diagnostics = ViewDiagnosticFlags.Ruler;
+        _hostPane.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
 
         _hostPane.LayoutStarted += (sender, args) =>
                                    {

+ 1 - 0
UICatalog/Scenarios/Bars.cs

@@ -136,6 +136,7 @@ public class Bars : Scenario
             Y = Pos.Bottom (label),
         };
         ConfigureMenu (bar);
+        bar.Arrangement = ViewArrangement.RightResizable;
 
         menuLikeExamples.Add (bar);
 

+ 1 - 0
UICatalog/Scenarios/HexEditor.cs

@@ -41,6 +41,7 @@ public class HexEditor : Scenario
             Title = _fileName ?? "Untitled",
             BorderStyle = LineStyle.Rounded,
         };
+        _hexView.Arrangement = ViewArrangement.Resizable;
         _hexView.Edited += _hexView_Edited;
         _hexView.PositionChanged += _hexView_PositionChanged;
         app.Add (_hexView);

+ 3 - 2
UICatalog/Scenarios/PosAlignDemo.cs

@@ -399,9 +399,10 @@ public sealed class PosAlignDemo : Scenario
             var v = new View
             {
                 Title = $"{i}",
+                Text = $"{i}",
                 BorderStyle = LineStyle.Dashed,
-                Height = 3,
-                Width = 5
+                Height = Dim.Auto (),
+                Width = Dim.Auto() + 2
             };
 
             v.X = Pos.Align (widthAligner.Alignment, widthAligner.AlignmentModes, i / 3);

+ 219 - 141
UICatalog/Scenarios/Shortcuts.cs

@@ -38,6 +38,7 @@ public class Shortcuts : Scenario
 
         var eventLog = new ListView
         {
+            Id = "eventLog",
             X = Pos.AnchorEnd (),
             Y = 0,
             Height = Dim.Fill (4),
@@ -46,70 +47,35 @@ public class Shortcuts : Scenario
             BorderStyle = LineStyle.Double,
             Title = "E_vents"
         };
-        eventLog.Width = Dim.Func (() => Math.Min (Application.Top.Viewport.Width / 2, eventLog?.MaxLength + eventLog.GetAdornmentsThickness ().Horizontal ?? 0));
+        eventLog.Width = Dim.Func (() => Math.Min (eventLog.SuperView!.Viewport.Width / 2, eventLog?.MaxLength + eventLog.GetAdornmentsThickness ().Horizontal ?? 0));
         Application.Top.Add (eventLog);
 
-        var vShortcut1 = new Shortcut
+        var alignKeysShortcut = new Shortcut
         {
+            Id = "alignKeysShortcut",
             X = 0,
+            Y = 0,
             Width = Dim.Fill () - Dim.Width (eventLog),
-            Title = "A_pp Shortcut",
-            Key = Key.F1,
-            Text = "Width is DimFIll",
-            KeyBindingScope = KeyBindingScope.Application,
-        };
-
-        Application.Top.Add (vShortcut1);
-
-        var vShortcut2 = new Shortcut
-        {
-            X = 0,
-            Y = Pos.Bottom (vShortcut1),
-            Width = 35,
-            Key = Key.F2,
-            Text = "Width is 35",
-            KeyBindingScope = KeyBindingScope.HotKey,
-            CommandView = new RadioGroup
-            {
-                Orientation = Orientation.Vertical,
-                RadioLabels = ["O_ne", "T_wo", "Th_ree", "Fo_ur"],
-                CanFocus = false
-            },
-        };
-
-        ((RadioGroup)vShortcut2.CommandView).SelectedItemChanged += (o, args) =>
-        {
-            eventSource.Add ($"SelectedItemChanged: {o.GetType ().Name} - {args.SelectedItem}");
-            eventLog.MoveDown ();
-        };
-
-        Application.Top.Add (vShortcut2);
-
-        var vShortcut3 = new Shortcut
-        {
-            X = 0,
-            Y = Pos.Bottom (vShortcut2),
+            HelpText = "Fill to log",
             CommandView = new CheckBox
             {
-                Text = "_Align",
+                Text = "_Align Keys",
                 CanFocus = false,
                 HighlightStyle = HighlightStyle.None,
             },
             Key = Key.F5.WithCtrl.WithAlt.WithShift,
-            HelpText = "Width is Fill",
-            Width = Dim.Fill () - Dim.Width (eventLog),
             KeyBindingScope = KeyBindingScope.HotKey,
         };
 
-        ((CheckBox)vShortcut3.CommandView).CheckedStateChanging += (s, e) =>
+        ((CheckBox)alignKeysShortcut.CommandView).CheckedStateChanging += (s, e) =>
         {
-            if (vShortcut3.CommandView is CheckBox cb)
+            if (alignKeysShortcut.CommandView is CheckBox cb)
             {
-                eventSource.Add ($"{vShortcut3.Id}.CommandView.CheckedStateChanging: {cb.Text}");
+                eventSource.Add ($"{alignKeysShortcut.Id}.CommandView.CheckedStateChanging: {cb.Text}");
                 eventLog.MoveDown ();
 
                 var max = 0;
-                IEnumerable<View> toAlign = Application.Top.Subviews.Where (v => v is Shortcut { Orientation: Orientation.Vertical, Width: not DimAbsolute });
+                IEnumerable<View> toAlign = Application.Top.Subviews.Where (v => v is Shortcut { Width: not DimAbsolute });
                 IEnumerable<View> enumerable = toAlign as View [] ?? toAlign.ToArray ();
 
                 if (e.NewValue == CheckState.Checked)
@@ -117,9 +83,7 @@ public class Shortcuts : Scenario
                     foreach (var view in enumerable)
                     {
                         var peer = (Shortcut)view;
-
-                        // DANGER: KeyView is internal so we can't access it. So we assume this is how it works.
-                        max = Math.Max (max, peer.Key.ToString ().GetColumns ());
+                        max = Math.Max (max, peer.KeyView.Text.GetColumns ());
                     }
                 }
 
@@ -130,149 +94,245 @@ public class Shortcuts : Scenario
                 }
             }
         };
-        Application.Top.Add (vShortcut3);
+        Application.Top.Add (alignKeysShortcut);
 
-        var vShortcut4 = new Shortcut
+        var commandFirstShortcut = new Shortcut
         {
-            Orientation = Orientation.Vertical,
+            Id = "commandFirstShortcut",
             X = 0,
-            Y = Pos.Bottom (vShortcut3),
-            Width = Dim.Width (vShortcut3),
-            CommandView = new Button
+            Y = Pos.Bottom (alignKeysShortcut),
+            Width = Dim.Fill () - Dim.Width (eventLog),
+            HelpText = "Show Command first",
+            CommandView = new CheckBox
             {
-                Title = "_Button",
-                ShadowStyle = ShadowStyle.None,
-                HighlightStyle = HighlightStyle.None
+                Text = "Command _First",
+                CanFocus = false,
+                HighlightStyle = HighlightStyle.None,
             },
-            HelpText = "Width is Fill",
-            Key = Key.K,
+            Key = Key.F.WithCtrl,
             KeyBindingScope = KeyBindingScope.HotKey,
         };
-        var button = (Button)vShortcut4.CommandView;
-        vShortcut4.Accepting += Button_Clicked;
-
-        Application.Top.Add (vShortcut4);
-
-        var vShortcut5 = new Shortcut
+        ((CheckBox)commandFirstShortcut.CommandView).CheckedState =
+            commandFirstShortcut.AlignmentModes.HasFlag (AlignmentModes.EndToStart) ? CheckState.UnChecked : CheckState.Checked;
+
+        ((CheckBox)commandFirstShortcut.CommandView).CheckedStateChanging += (s, e) =>
+                                                                         {
+                                                                             if (commandFirstShortcut.CommandView is CheckBox cb)
+                                                                             {
+                                                                                 eventSource.Add ($"{commandFirstShortcut.Id}.CommandView.CheckedStateChanging: {cb.Text}");
+                                                                                 eventLog.MoveDown ();
+
+                                                                                 var max = 0;
+                                                                                 IEnumerable<View> toAlign = Application.Top.Subviews.Where (v => v is Shortcut { Width: not DimAbsolute });
+                                                                                 IEnumerable<View> enumerable = toAlign as View [] ?? toAlign.ToArray ();
+
+                                                                                 foreach (var view in enumerable)
+                                                                                 {
+                                                                                     var peer = (Shortcut)view;
+                                                                                     if (e.NewValue == CheckState.Checked)
+                                                                                     {
+                                                                                         peer.AlignmentModes &= ~AlignmentModes.EndToStart;
+                                                                                     }
+                                                                                     else
+                                                                                     {
+                                                                                         peer.AlignmentModes |= AlignmentModes.EndToStart;
+                                                                                     }
+                                                                                 }
+                                                                             }
+                                                                         };
+
+        Application.Top.Add (commandFirstShortcut);
+
+        var canFocusShortcut = new Shortcut
         {
-            Orientation = Orientation.Vertical,
+            Id = "canFocusShortcut",
             X = 0,
-            Y = Pos.Bottom (vShortcut4),
-            Width = Dim.Width (vShortcut4),
-
+            Y = Pos.Bottom (commandFirstShortcut),
+            Width = Dim.Fill () - Dim.Width (eventLog),
             Key = Key.F4,
-            HelpText = "CommandView.CanFocus",
+            HelpText = "Changes all Command.CanFocus",
             KeyBindingScope = KeyBindingScope.HotKey,
             CommandView = new CheckBox { Text = "_CanFocus" },
         };
 
-        ((CheckBox)vShortcut5.CommandView).CheckedStateChanging += (s, e) =>
+        ((CheckBox)canFocusShortcut.CommandView).CheckedStateChanging += (s, e) =>
         {
-            if (vShortcut5.CommandView is CheckBox cb)
+            if (canFocusShortcut.CommandView is CheckBox cb)
             {
                 eventSource.Add ($"Toggle: {cb.Text}");
                 eventLog.MoveDown ();
+                //cb.CanFocus = e.NewValue == CheckState.Checked;
 
-                //foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!)
-                //{
-                //    if (peer.CanFocus)
-                //    {
-                //        peer.CommandView.CanFocus = e.NewValue == CheckState.Checked;
-                //    }
-                //}
+                foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!)
+                {
+                    if (peer.CanFocus)
+                    {
+                        peer.CommandView.CanFocus = e.NewValue == CheckState.Checked;
+                    }
+                }
             }
         };
-        Application.Top.Add (vShortcut5);
+        Application.Top.Add (canFocusShortcut);
+
+        var appShortcut = new Shortcut
+        {
+            Id = "appShortcut",
+            X = 0,
+            Y = Pos.Bottom (canFocusShortcut),
+            Width = Dim.Fill (Dim.Func (() => eventLog.Frame.Width)),
+            Title = "A_pp Shortcut",
+            Key = Key.F1,
+            Text = "Width is DimFill",
+            KeyBindingScope = KeyBindingScope.Application,
+        };
+
+        Application.Top.Add (appShortcut);
+
 
-        var vShortcutSlider = new Shortcut
+        var buttonShortcut = new Shortcut
         {
-            Orientation = Orientation.Vertical,
+            Id = "buttonShortcut",
             X = 0,
-            Y = Pos.Bottom (vShortcut5),
-            HelpText = "Width is Fill",
-            Width = Dim.Width (vShortcut5),
+            Y = Pos.Bottom (appShortcut),
+            Width = Dim.Fill () - Dim.Width (eventLog),
+            HelpText = "Accepting pops MB",
+            CommandView = new Button
+            {
+                Title = "_Button",
+                ShadowStyle = ShadowStyle.None,
+                HighlightStyle = HighlightStyle.None
+            },
+            Key = Key.K,
+            KeyBindingScope = KeyBindingScope.HotKey,
+        };
+        var button = (Button)buttonShortcut.CommandView;
+        buttonShortcut.Accepting += Button_Clicked;
+
+        Application.Top.Add (buttonShortcut);
+
 
+        var radioGroupShortcut = new Shortcut
+        {
+            Id = "radioGroupShortcut",
+            X = 0,
+            Y = Pos.Bottom (buttonShortcut),
+            Key = Key.F2,
+            Width = Dim.Fill () - Dim.Width (eventLog),
             KeyBindingScope = KeyBindingScope.HotKey,
-            CommandView = new Slider<string>
+            CommandView = new RadioGroup
             {
                 Orientation = Orientation.Vertical,
+                RadioLabels = ["O_ne", "T_wo", "Th_ree", "Fo_ur"],
+            },
+        };
+
+        ((RadioGroup)radioGroupShortcut.CommandView).SelectedItemChanged += (o, args) =>
+                                                                            {
+                                                                                eventSource.Add ($"SelectedItemChanged: {o.GetType ().Name} - {args.SelectedItem}");
+                                                                                eventLog.MoveDown ();
+                                                                            };
+
+        Application.Top.Add (radioGroupShortcut);
+
+        var sliderShortcut = new Shortcut
+        {
+            Id = "sliderShortcut",
+            X = 0,
+            Y = Pos.Bottom (radioGroupShortcut),
+            Width = Dim.Fill () - Dim.Width (eventLog),
+            KeyBindingScope = KeyBindingScope.HotKey,
+            HelpText = "Sliders work!",
+            CommandView = new Slider<string>
+            {
+                Orientation = Orientation.Horizontal,
                 AllowEmpty = true
             },
             Key = Key.F5,
         };
 
-        ((Slider<string>)vShortcutSlider.CommandView).Options = new () { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } };
-        ((Slider<string>)vShortcutSlider.CommandView).SetOption (0);
+        ((Slider<string>)sliderShortcut.CommandView).Options = new () { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } };
+        ((Slider<string>)sliderShortcut.CommandView).SetOption (0);
 
-        ((Slider<string>)vShortcutSlider.CommandView).OptionsChanged += (o, args) =>
+        ((Slider<string>)sliderShortcut.CommandView).OptionsChanged += (o, args) =>
         {
             eventSource.Add ($"OptionsChanged: {o.GetType ().Name} - {string.Join (",", ((Slider<string>)o).GetSetOptions ())}");
             eventLog.MoveDown ();
         };
 
-        Application.Top.Add (vShortcutSlider);
+        Application.Top.Add (sliderShortcut);
+
+
+        var noCommandShortcut = new Shortcut
+        {
+            Id = "noCommandShortcut",
+            X = 0,
+            Y = Pos.Bottom (sliderShortcut),
+            Width = Dim.Width (sliderShortcut),
+            HelpText = "No Command",
+            Key = Key.D0
+        };
+
+        Application.Top.Add (noCommandShortcut);
 
-        var vShortcut6 = new Shortcut
+        var noKeyShortcut = new Shortcut
         {
-            Orientation = Orientation.Vertical,
+            Id = "noKeyShortcut",
             X = 0,
-            Y = Pos.Bottom (vShortcutSlider),
-            Width = Dim.Width (vShortcutSlider),
+            Y = Pos.Bottom (noCommandShortcut),
+            Width = Dim.Width (noCommandShortcut),
 
-            Title = "_No Key",
+            Title = "No Ke_y",
             HelpText = "Keyless",
         };
 
-        Application.Top.Add (vShortcut6);
+        Application.Top.Add (noKeyShortcut);
 
 
-        var vShortcut7 = new Shortcut
+        var noHelpShortcut = new Shortcut
         {
-            Orientation = Orientation.Vertical,
+            Id = "noHelpShortcut",
             X = 0,
-            Y = Pos.Bottom (vShortcut6),
-            Width = Dim.Width (vShortcutSlider),
+            Y = Pos.Bottom (noKeyShortcut),
+            Width = Dim.Width (noKeyShortcut),
             Key = Key.F6,
             Title = "Not _very much help",
             HelpText = "",
         };
 
-        Application.Top.Add (vShortcut7);
-        vShortcut7.SetFocus ();
+        Application.Top.Add (noHelpShortcut);
+        noHelpShortcut.SetFocus ();
 
         var framedShortcut = new Shortcut
         {
+            Id = "framedShortcut",
             X = 0,
-            Y = Pos.Bottom(vShortcut7) + 1,
-            Width = Dim.Auto(),
-            Title = "C",
-            Key = Key.K,
-            Text = "H",
+            Y = Pos.Bottom (noHelpShortcut) + 1,
+            Title = "Framed",
+            Key = Key.K.WithCtrl,
+            Text = "Resize frame",
             BorderStyle = LineStyle.Dotted,
-            Arrangement = ViewArrangement.Resizable,
-            CanFocus = false,
-            // Orientation = Orientation.Horizontal,
-            //AlignmentModes = AlignmentModes.EndToStart
-
+            Arrangement = ViewArrangement.RightResizable | ViewArrangement.BottomResizable,
         };
         framedShortcut.Orientation = Orientation.Horizontal;
         framedShortcut.Padding.Thickness = new (0, 1, 0, 0);
+        framedShortcut.Padding.Diagnostics = ViewDiagnosticFlags.Ruler;
         framedShortcut.CommandView.Margin.ColorScheme = framedShortcut.CommandView.ColorScheme = Colors.ColorSchemes ["Error"];
         framedShortcut.HelpView.Margin.ColorScheme = framedShortcut.HelpView.ColorScheme = Colors.ColorSchemes ["Dialog"];
         framedShortcut.KeyView.Margin.ColorScheme = framedShortcut.KeyView.ColorScheme = Colors.ColorSchemes ["Menu"];
+        framedShortcut.ColorScheme = Colors.ColorSchemes ["Toplevel"];
         Application.Top.Add (framedShortcut);
 
         // Horizontal
-        var hShortcut1 = new Shortcut
+        var progressShortcut = new Shortcut
         {
+            Id = "progressShortcut",
             X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
-            Y = Pos.Bottom (eventLog) + 1,
+            Y = Pos.AnchorEnd () - 1,
             Key = Key.F7,
             HelpText = "Horizontal",
-            CanFocus = false
         };
 
-        hShortcut1.CommandView = new ProgressBar
+        progressShortcut.CommandView = new ProgressBar
         {
             Text = "Progress",
             Title = "P",
@@ -281,9 +341,9 @@ public class Shortcuts : Scenario
             Height = 1,
             ProgressBarStyle = ProgressBarStyle.Continuous
         };
-        hShortcut1.CommandView.Width = 10;
-        hShortcut1.CommandView.Height = 1;
-        hShortcut1.CommandView.CanFocus = false;
+        progressShortcut.CommandView.Width = 10;
+        progressShortcut.CommandView.Height = 1;
+        progressShortcut.CommandView.CanFocus = false;
 
         Timer timer = new (10)
         {
@@ -291,7 +351,7 @@ public class Shortcuts : Scenario
         };
         timer.Elapsed += (o, args) =>
         {
-            if (hShortcut1.CommandView is ProgressBar pb)
+            if (progressShortcut.CommandView is ProgressBar pb)
             {
                 if (pb.Fraction == 1.0)
                 {
@@ -306,73 +366,91 @@ public class Shortcuts : Scenario
         };
         timer.Start ();
 
-        Application.Top.Add (hShortcut1);
+        Application.Top.Add (progressShortcut);
 
         var textField = new TextField ()
         {
             Text = "Edit me",
             Width = 10,
             Height = 1,
-            CanFocus = true
         };
 
-        var hShortcut2 = new Shortcut
+        var textFieldShortcut = new Shortcut
         {
-            Orientation = Orientation.Horizontal,
+            Id = "textFieldShortcut",
             X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
-            Y = Pos.Top (hShortcut1),
+            Y = Pos.AnchorEnd () - 1,
             Key = Key.F8,
             HelpText = "TextField",
             CanFocus = true,
             CommandView = textField,
         };
+        textField.CanFocus = true;
 
-        Application.Top.Add (hShortcut2);
+        Application.Top.Add (textFieldShortcut);
 
-        var hShortcutBG = new Shortcut
+        var bgColorShortcut = new Shortcut
         {
-            Orientation = Orientation.Horizontal,
-            X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1) - 1,
-            Y = Pos.Top (hShortcut2),
+            Id = "bgColorShortcut",
+            X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
+            Y = Pos.AnchorEnd (),
             Key = Key.F9,
-            HelpText = "BG Color",
-            CanFocus = false
+            HelpText = "Cycles BG Color",
         };
 
         var bgColor = new ColorPicker16 ()
         {
             BoxHeight = 1,
             BoxWidth = 1,
-            CanFocus = false
         };
+
+        bgColorShortcut.Selecting += (o, args) =>
+                                     {
+                                         //args.Cancel = true;
+                                     };
+
+        bgColorShortcut.Accepting += (o, args) =>
+                                     {
+                                         if (bgColor.SelectedColor == ColorName16.White)
+                                         {
+                                             bgColor.SelectedColor = ColorName16.Black;
+
+                                             return;
+                                         }
+                                         bgColor.SelectedColor++;
+                                         args.Cancel = true;
+                                     };
+
         bgColor.ColorChanged += (o, args) =>
         {
+            eventSource.Add ($"ColorChanged: {o.GetType ().Name} - {args.CurrentValue}");
+            eventLog.MoveDown ();
+
             Application.Top.ColorScheme = new ColorScheme (Application.Top.ColorScheme)
             {
                 Normal = new Attribute (Application.Top.ColorScheme.Normal.Foreground, args.CurrentValue),
             };
         };
-        hShortcutBG.CommandView = bgColor;
+        bgColorShortcut.CommandView = bgColor;
 
-        Application.Top.Add (hShortcutBG);
+        Application.Top.Add (bgColorShortcut);
 
-        var hShortcut3 = new Shortcut
+        var appQuitShortcut = new Shortcut
         {
-            Orientation = Orientation.Horizontal,
+            Id = "appQuitShortcut",
             X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
-            Y = Pos.Top (hShortcut2),
+            Y = Pos.AnchorEnd () - 1,
             Key = Key.Esc,
             KeyBindingScope = KeyBindingScope.Application,
             Title = "Quit",
             HelpText = "App Scope",
-            CanFocus = false
         };
-        hShortcut3.Accepting += (o, args) =>
+        appQuitShortcut.Accepting += (o, args) =>
         {
             Application.RequestStop ();
         };
 
-        Application.Top.Add (hShortcut3);
+        Application.Top.Add (appQuitShortcut);
 
         foreach (View sh in Application.Top.Subviews.Where (v => v is Shortcut)!)
         {

+ 8 - 24
UnitTests/Drawing/ThicknessTests.cs

@@ -54,14 +54,12 @@ public class ThicknessTests (ITestOutputHelper output)
         ((FakeDriver)Application.Driver!).SetBufferSize (60, 60);
         var t = new Thickness (0, 0, 0, 0);
         var r = new Rectangle (5, 5, 40, 15);
-        View.Diagnostics |= ViewDiagnosticFlags.Padding;
 
         Application.Driver?.FillRect (
                                      new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
                                      (Rune)' '
                                     );
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Padding, "Test");
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -71,14 +69,12 @@ public class ThicknessTests (ITestOutputHelper output)
 
         t = new Thickness (1, 1, 1, 1);
         r = new Rectangle (5, 5, 40, 15);
-        View.Diagnostics |= ViewDiagnosticFlags.Padding;
 
         Application.Driver?.FillRect (
                                      new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
                                      (Rune)' '
                                     );
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Padding, "Test");
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -102,14 +98,12 @@ public class ThicknessTests (ITestOutputHelper output)
 
         t = new Thickness (1, 2, 3, 4);
         r = new Rectangle (5, 5, 40, 15);
-        View.Diagnostics |= ViewDiagnosticFlags.Padding;
 
         Application.Driver?.FillRect (
                                      new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
                                      (Rune)' '
                                     );
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Padding, "Test");
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -133,14 +127,12 @@ public class ThicknessTests (ITestOutputHelper output)
 
         t = new Thickness (-1, 1, 1, 1);
         r = new Rectangle (5, 5, 40, 15);
-        View.Diagnostics |= ViewDiagnosticFlags.Padding;
 
         Application.Driver?.FillRect (
                                      new Rectangle (0, 0, Application.Driver!.Cols, Application.Driver!.Rows),
                                      (Rune)' '
                                     );
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Padding, "Test");
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -179,9 +171,7 @@ public class ThicknessTests (ITestOutputHelper output)
         var r = new Rectangle (2, 2, 40, 15);
         Application.RunIteration (ref rs);
 
-        View.Diagnostics |= ViewDiagnosticFlags.Ruler;
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Ruler, "Test");
 
         TestHelpers.AssertDriverContentsAre (
                                              @"
@@ -212,9 +202,7 @@ public class ThicknessTests (ITestOutputHelper output)
         r = new Rectangle (1, 1, 40, 15);
         top.SetNeedsDisplay ();
         Application.RunIteration (ref rs);
-        View.Diagnostics |= ViewDiagnosticFlags.Ruler;
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Ruler,  "Test");
 
         TestHelpers.AssertDriverContentsAre (
                                              @"
@@ -245,9 +233,7 @@ public class ThicknessTests (ITestOutputHelper output)
         r = new Rectangle (2, 2, 40, 15);
         top.SetNeedsDisplay ();
         Application.RunIteration (ref rs);
-        View.Diagnostics |= ViewDiagnosticFlags.Ruler;
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Ruler,  "Test");
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -278,9 +264,7 @@ public class ThicknessTests (ITestOutputHelper output)
         r = new Rectangle (5, 5, 40, 15);
         top.SetNeedsDisplay ();
         Application.RunIteration (ref rs);
-        View.Diagnostics |= ViewDiagnosticFlags.Ruler;
-        t.Draw (r, "Test");
-        View.Diagnostics = ViewDiagnosticFlags.Off;
+        t.Draw (r, ViewDiagnosticFlags.Ruler, "Test");
 
         TestHelpers.AssertDriverContentsWithFrameAre (
                                                       @"

+ 2 - 1
UnitTests/View/Adornment/MarginTests.cs

@@ -9,6 +9,8 @@ public class MarginTests (ITestOutputHelper output)
     public void Margin_Uses_SuperView_ColorScheme ()
     {
         ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        View.Diagnostics = ViewDiagnosticFlags.Padding;
+
         var view = new View { Height = 3, Width = 3 };
         view.Margin.Thickness = new (1);
 
@@ -27,7 +29,6 @@ public class MarginTests (ITestOutputHelper output)
 
         superView.BeginInit ();
         superView.EndInit ();
-        View.Diagnostics = ViewDiagnosticFlags.Padding;
         view.SetNeedsDisplay();
         view.Draw ();
         View.Diagnostics = ViewDiagnosticFlags.Off;

+ 1 - 2
UnitTests/View/Adornment/PaddingTests.cs

@@ -11,6 +11,7 @@ public class PaddingTests (ITestOutputHelper output)
         ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
         var view = new View { Height = 3, Width = 3 };
         view.Padding.Thickness = new (1);
+        view.Padding.Diagnostics = ViewDiagnosticFlags.Padding;
 
         view.ColorScheme = new()
         {
@@ -22,9 +23,7 @@ public class PaddingTests (ITestOutputHelper output)
 
         view.BeginInit ();
         view.EndInit ();
-        View.Diagnostics = ViewDiagnosticFlags.Padding;
         view.Draw ();
-        View.Diagnostics = ViewDiagnosticFlags.Off;
 
         TestHelpers.AssertDriverContentsAre (
                                              @"

+ 1 - 3
UnitTests/View/Draw/DrawTests.cs

@@ -43,7 +43,7 @@ public class DrawTests (ITestOutputHelper _output)
             Width = 3, Height = 3
         };
         view.Margin.Thickness = new (1);
-        View.Diagnostics = ViewDiagnosticFlags.Padding;
+        view.Margin.Diagnostics = ViewDiagnosticFlags.Padding;
         view.BeginInit ();
         view.EndInit ();
         view.Draw ();
@@ -59,8 +59,6 @@ public class DrawTests (ITestOutputHelper _output)
 
         view.AddRune (1, 1, Rune.ReplacementChar);
         Assert.Equal ((Rune)'M', Application.Driver?.Contents! [3, 3].Rune);
-
-        View.Diagnostics = ViewDiagnosticFlags.Off;
     }
 
     [Theory]

+ 4 - 5
UnitTests/View/Layout/Dim.FillTests.cs

@@ -16,8 +16,7 @@ public class DimFillTests (ITestOutputHelper output)
         RunState rs = Application.Begin (top);
         ((FakeDriver)Application.Driver!).SetBufferSize (32, 5);
 
-        //view.SetNeedsLayout ();
-        top.LayoutSubviews ();
+        top.Layout ();
 
         //view.SetRelativeLayout (new (0, 0, 32, 5));
         Assert.Equal (32, view.Frame.Width);
@@ -61,7 +60,7 @@ public class DimFillTests (ITestOutputHelper output)
         super.Add (view);
         super.BeginInit ();
         super.EndInit ();
-        super.LayoutSubviews ();
+        super.Layout ();
 
         Assert.Equal (25, super.Frame.Width);
         Assert.Equal (25, super.Frame.Height);
@@ -103,7 +102,7 @@ public class DimFillTests (ITestOutputHelper output)
         super.Add (view);
         super.BeginInit ();
         super.EndInit ();
-        super.LayoutSubviews ();
+        super.Layout ();
 
         Assert.Equal (25, super.Frame.Width);
         Assert.Equal (25, super.Frame.Height);
@@ -167,7 +166,7 @@ public class DimFillTests (ITestOutputHelper output)
         super.Add (view);
 
         view.Text = "New text\nNew line";
-        super.LayoutSubviews ();
+        super.Layout ();
         Rectangle expectedViewBounds = new (0, 0, 30, 80);
 
         Assert.Equal (expectedViewBounds, view.Viewport);

+ 6 - 2
UnitTests/Views/HexViewTests.cs

@@ -24,6 +24,7 @@ public class HexViewTests
         var hv = new HexView (LoadStream (null, out long _)) { Width = width, Height = 10, AddressWidth = 0 };
         hv.Layout ();
 
+        Assert.Equal (width, hv.Frame.Width);
         Assert.Equal (expectedBpl, hv.BytesPerLine);
     }
 
@@ -370,20 +371,21 @@ public class HexViewTests
         Application.Top = new Toplevel ();
         Application.Top.Add (hv);
 
-        hv.Layout ();
+        Application.Top.Layout ();
 
         Assert.True (hv.NewKeyDownEvent (Key.End));
         Assert.Equal (MEM_STRING_LENGTH - 1, hv.DisplayStart);
         Assert.Equal (MEM_STRING_LENGTH, hv.Address);
 
         hv.Source = new MemoryStream ();
+        Application.Top.Layout ();
         Assert.Equal (0, hv.DisplayStart);
         Assert.Equal (0, hv.Address);
 
         hv.Source = LoadStream (null, out _);
         hv.Width = Dim.Fill ();
         hv.Height = Dim.Fill ();
-        Application.Top.LayoutSubviews ();
+        Application.Top.Layout ();
         Assert.Equal (0, hv.DisplayStart);
         Assert.Equal (0, hv.Address);
 
@@ -392,8 +394,10 @@ public class HexViewTests
         Assert.Equal (MEM_STRING_LENGTH, hv.Address);
 
         hv.Source = new MemoryStream ();
+        Application.Top.Layout ();
         Assert.Equal (0, hv.DisplayStart);
         Assert.Equal (0, hv.Address);
+
         Application.Top.Dispose ();
         Application.ResetState (true);
     }

+ 36 - 5
UnitTests/Views/ShortcutTests.cs

@@ -95,20 +95,51 @@ public class ShortcutTests
     {
         var shortcut = new Shortcut
         {
-            Title = command,
             HelpText = help,
-            Key = key
+            Key = key,
+            Title = command,
         };
 
-        Assert.IsType<DimAuto> (shortcut.Width);
-        Assert.IsType<DimAuto> (shortcut.Height);
-        shortcut.SetRelativeLayout (new (100, 100));
+        shortcut.Layout();
 
         // |0123456789
         // | C  H  K |
         Assert.Equal (expectedWidth, shortcut.Frame.Width);
+
+        shortcut = new Shortcut
+        {
+            HelpText = help,
+            Title = command,
+            Key = key
+        };
+
+        shortcut.Layout ();
+        Assert.Equal (expectedWidth, shortcut.Frame.Width);
+
+        shortcut = new Shortcut
+        {
+            HelpText = help,
+            Key = key,
+            Title = command,
+        };
+
+        shortcut.Layout ();
+        Assert.Equal (expectedWidth, shortcut.Frame.Width);
+
+        shortcut = new Shortcut
+        {
+            Key = key,
+            HelpText = help,
+            Title = command,
+        };
+
+        shortcut.Layout ();
+        Assert.Equal (expectedWidth, shortcut.Frame.Width);
+
     }
 
+
+
     [Theory]
     [InlineData (0, 0, 3, 3)]
     [InlineData (1, 0, 3, 3)]

+ 2 - 0
UnitTests/Views/WindowTests.cs

@@ -121,6 +121,7 @@ public class WindowTests
     {
         // Parameterless
         using var defaultWindow = new Window ();
+        defaultWindow.Layout ();
         Assert.NotNull (defaultWindow);
         Assert.Equal (string.Empty, defaultWindow.Title);
 
@@ -148,6 +149,7 @@ public class WindowTests
 
         // Empty Rect
         using var windowWithFrameRectEmpty = new Window { Frame = Rectangle.Empty, Title = "title" };
+        windowWithFrameRectEmpty.Layout ();
         Assert.NotNull (windowWithFrameRectEmpty);
         Assert.Equal ("title", windowWithFrameRectEmpty.Title);
         Assert.True (windowWithFrameRectEmpty.CanFocus);