瀏覽代碼

Added horizontal scenario stuff

Tig 1 年之前
父節點
當前提交
f02ca8abc0

+ 4 - 1
Terminal.Gui/Input/CommandContext.cs

@@ -1,14 +1,17 @@
 #nullable enable
 namespace Terminal.Gui;
+
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
 /// <summary>
 ///     Provides context for a <see cref="Command"/> that is being invoked.
 /// </summary
 /// <remarks>
 ///     <para>
 ///         To define a <see cref="Command"/> that is invoked with context,
-///         use <see cref="View.AddCommand(Command,Func{CommandContext,Nullable{bool}})"/>
+///         use <see cref="View.AddCommand(Command,Func{CommandContext,System.Nullable{bool}})"/>.
 ///     </para>
 /// </remarks>
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
 public record struct CommandContext
 {
     /// <summary>

+ 18 - 0
Terminal.Gui/View/Layout/Pos.cs

@@ -336,6 +336,24 @@ public abstract class Pos
     /// <returns></returns>
     internal virtual bool ReferencesOtherViews () { return false; }
 
+    public bool Has (Type type, out Pos pos)
+    {
+        pos = this;
+        if (type == GetType())
+        {
+            return true;
+        }
+
+        // If we are a PosCombine, we have to check the left and right
+        // to see if they are of the type we are looking for.
+        if (this is PosCombine { } combine && (combine.Left.Has (type, out pos) || combine.Right.Has (type, out pos)))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
     #endregion virtual methods
 
     #region operators

+ 51 - 52
Terminal.Gui/View/Layout/PosAlign.cs

@@ -70,59 +70,67 @@ public class PosAlign : Pos
         List<int> dimensionsList = new ();
 
         // PERF: If this proves a perf issue, consider caching a ref to this list in each item
-        List<View> viewsInGroup = views.Where (
-                                               v =>
-                                               {
-                                                   return dimension switch
-                                                   {
-                                                       Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId,
-                                                       Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
-                                                       _ => false
-                                                   };
-                                               })
+        List<PosAlign?> posAligns = views.Select (
+                                                v =>
+                                                {
+                                                    switch (dimension)
+                                                    {
+                                                        case Dimension.Width when v.X.Has (typeof (PosAlign), out var pos):
+
+                                                            if (pos is PosAlign posAlignX && posAlignX.GroupId == groupId)
+                                                            {
+                                                                return posAlignX;
+                                                            }
+
+                                                            break;
+                                                        case Dimension.Height when v.Y.Has (typeof (PosAlign), out var pos):
+                                                            if (pos is PosAlign posAlignY && posAlignY.GroupId == groupId)
+                                                            {
+                                                                return posAlignY;
+                                                            }
+
+                                                            break;
+                                                    }
+
+                                                    return null;
+                                                })
                                        .ToList ();
 
-        if (viewsInGroup.Count == 0)
-        {
-            return;
-        }
-
         // PERF: We iterate over viewsInGroup multiple times here.
 
         Aligner? firstInGroup = null;
 
         // Update the dimensionList with the sizes of the views
-        for (var index = 0; index < viewsInGroup.Count; index++)
+        for (var index = 0; index < posAligns.Count; index++)
         {
-            View view = viewsInGroup [index];
-            PosAlign? posAlign = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign;
-
-            if (posAlign is { })
+            if (posAligns [index] is { })
             {
-                if (index == 0)
+                if (firstInGroup is null)
                 {
-                    firstInGroup = posAlign.Aligner;
+                    firstInGroup = posAligns [index]!.Aligner;
                 }
 
-                dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height);
+                dimensionsList.Add (dimension == Dimension.Width ? views [index].Frame.Width : views [index].Frame.Height);
             }
         }
 
+        if (firstInGroup is null)
+        {
+            return;
+        }
+
         // Update the first item in the group with the new container size.
-        firstInGroup!.ContainerSize = size;
+        firstInGroup.ContainerSize = size;
 
         // Align
         int [] locations = firstInGroup.Align (dimensionsList.ToArray ());
 
         // Update the cached location for each item
-        for (var index = 0; index < viewsInGroup.Count; index++)
+        for (int posIndex = 0, locIndex = 0; posIndex < posAligns.Count; posIndex++)
         {
-            View view = viewsInGroup [index];
-            PosAlign? align = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign;
-
-            if (align is { })
+            if (posAligns [posIndex] is { })
             {
-                align._cachedLocation = locations [index];
+                posAligns [posIndex]!._cachedLocation = locations [locIndex++];
             }
         }
     }
@@ -168,6 +176,14 @@ public class PosAlign : Pos
         return 0;
     }
 
+    // TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
+    /// <summary>
+    /// Returns the minimum size a group of views with the same <paramref name="groupId"/> can be.
+    /// </summary>
+    /// <param name="groupId"></param>
+    /// <param name="views"></param>
+    /// <param name="dimension"></param>
+    /// <returns></returns>
     public static int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension)
     {
         List<int> dimensionsList = new ();
@@ -177,11 +193,11 @@ public class PosAlign : Pos
                                                v =>
                                                {
                                                    return dimension switch
-                                                          {
-                                                              Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId,
-                                                              Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
-                                                              _ => false
-                                                          };
+                                                   {
+                                                       Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId,
+                                                       Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
+                                                       _ => false
+                                                   };
                                                })
                                        .ToList ();
 
@@ -192,8 +208,6 @@ public class PosAlign : Pos
 
         // PERF: We iterate over viewsInGroup multiple times here.
 
-        Aligner? firstInGroup = null;
-
         // Update the dimensionList with the sizes of the views
         for (var index = 0; index < viewsInGroup.Count; index++)
         {
@@ -203,26 +217,11 @@ public class PosAlign : Pos
 
             if (posAlign is { })
             {
-                if (index == 0)
-                {
-                    firstInGroup = posAlign.Aligner;
-
-                    //if (!posAlign._cachedLocation.HasValue)
-                    //{
-                    //    AlignAndUpdateGroup (groupId, viewsInGroup, dimension, firstInGroup.ContainerSize );
-                    //}
-
-                }
-
                 dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height);
             }
         }
 
         // Align
-        var aligner = firstInGroup;
-        aligner.ContainerSize = dimensionsList.Sum();
-        int [] locations = aligner.Align (dimensionsList.ToArray ());
-
         return dimensionsList.Sum ();
     }
 }

+ 1 - 1
Terminal.Gui/Views/ColorPicker.cs

@@ -48,7 +48,7 @@ public class ColorPicker : View
 
     private void ColorPicker_MouseClick (object sender, MouseEventEventArgs me)
     {
-        if (CanFocus)
+       // if (CanFocus)
         {
             Cursor = new Point (me.MouseEvent.Position.X / _boxWidth, me.MouseEvent.Position.Y / _boxHeight);
             SetFocus ();

+ 57 - 34
Terminal.Gui/Views/Shortcut.cs

@@ -27,8 +27,7 @@ namespace Terminal.Gui;
 ///         right side.
 ///     </para>
 ///     <para>
-///         The command text can be set by setting the <see cref="CommandView"/>'s Text property or by setting
-///         <see cref="View.Title"/>.
+///         The command text can be set by setting the <see cref="CommandView"/>'s Text property.
 ///     </para>
 ///     <para>
 ///         The help text can be set by setting the <see cref="HelpText"/> property or by setting <see cref="View.Text"/>.
@@ -59,27 +58,31 @@ public class Shortcut : View
 
         TitleChanged += Shortcut_TitleChanged; // This needs to be set before CommandView is set
 
-        CommandView = new ();
+        CommandView = new ()
+        {
+            Width = Dim.Auto (),
+            Height = Dim.Auto (),
+        };
 
         HelpView.Id = "_helpView";
         HelpView.CanFocus = false;
         SetHelpViewDefaultLayout ();
         Add (HelpView);
-        HelpView.MouseClick += Shortcut_MouseClick;
 
         KeyView.Id = "_keyView";
         KeyView.CanFocus = false;
         SetKeyViewDefaultLayout ();
         Add (KeyView);
 
+        // If the user clicks anywhere on the Shortcut, other than the CommandView, invoke the Command
+        MouseClick += Shortcut_MouseClick;
+        HelpView.MouseClick += Shortcut_MouseClick;
         KeyView.MouseClick += Shortcut_MouseClick;
 
-        MouseClick += Shortcut_MouseClick;
+        LayoutStarted += OnLayoutStarted;
 
         Initialized += OnInitialized;
 
-        LayoutStarted += OnLayoutStarted;
-
         return;
 
         void OnInitialized (object sender, EventArgs e)
@@ -111,10 +114,19 @@ public class Shortcut : View
         // Helper to set Width consistently
         Dim GetWidthDimAuto ()
         {
+            // TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
             return Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width)));
         }
     }
 
+
+    /// <summary>
+    ///     Gets or sets the <see cref="Orientation"/> for this <see cref="Shortcut"/>. The default is
+    ///     <see cref="Orientation.Horizontal"/>, which is ideal for status bars and toolbars. If set to <see cref="Orientation.Vertical"/>,
+    ///     the Shortcut will be configured for vertical layout, which is ideal for menus.
+    /// </summary>
+    public Orientation Orientation { get; set; } = Orientation.Horizontal;
+
     // When one of the subviews is "empty" we don't want to show it. So we
     // Use Add/Remove. We need to be careful to add them in the right order
     // so Pos.Align works correctly.
@@ -122,7 +134,7 @@ public class Shortcut : View
     {
         RemoveAll ();
 
-        if (!string.IsNullOrEmpty (CommandView.Text))
+        if (CommandView.Visible)
         {
             Add (CommandView);
         }
@@ -161,7 +173,7 @@ public class Shortcut : View
             if (currentWidth < _minimumDimAutoWidth)
             {
                 int delta = _minimumDimAutoWidth.Value - currentWidth;
-                int maxHelpWidth = int.Max (0, HelpView.Text.GetColumns () + 2 - delta);
+                int maxHelpWidth = int.Max (0, HelpView.Text.GetColumns () + Margin.Thickness.Horizontal - delta);
 
                 switch (maxHelpWidth)
                 {
@@ -180,13 +192,14 @@ public class Shortcut : View
 
                     case 2:
                         // Scrunch just the right margin
-                        HelpView.Margin.Thickness = new (1, 0, 0, 0);
+                        var t = GetMarginThickness ();
+                        HelpView.Margin.Thickness = new (t.Right, t.Top, t.Left - 1, t.Bottom);
 
                         break;
 
                     default:
                         // Default margin
-                        HelpView.Margin.Thickness = new (1, 0, 1, 0);
+                        HelpView.Margin.Thickness = GetMarginThickness ();
 
                         break;
                 }
@@ -208,6 +221,18 @@ public class Shortcut : View
         }
     }
 
+    private Thickness GetMarginThickness ()
+    {
+        if (Orientation == Orientation.Vertical)
+        {
+            return new Thickness (1, 0, 1, 0);
+        }
+        else
+        {
+            return new Thickness (1, 0, 1, 0);
+        }
+    }
+
     private Color? _savedForeColor;
 
     private void Shortcut_Highlight (object sender, HighlightEventArgs e)
@@ -339,18 +364,26 @@ public class Shortcut : View
 
             // TODO: Determine if it makes sense to allow the CommandView to be focusable.
             // Right now, we don't set CanFocus to false here.
-            _commandView.CanFocus = false;
+            //_commandView.CanFocus = true;
+
+            //// Bar will set the width of all CommandViews to the width of the widest CommandViews.
+            ////if (_commandView.Width == Dim.Absolute(0))
+            //{
+            //    _commandView.Width = Dim.Auto ();
+            //}
+
+            ////if (_commandView.Height == Dim.Absolute (0))
+            //{
+            //    _commandView.Height = Dim.Auto ();
+            //}
 
-            // Bar will set the width of all CommandViews to the width of the widest CommandViews.
-            _commandView.Width = Dim.Auto ();
-            _commandView.Height = Dim.Auto ();
             _commandView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
             _commandView.Y = 0; //Pos.Center ();
 
             _commandView.MouseClick += Shortcut_MouseClick;
             _commandView.Accept += CommandViewAccept;
 
-            _commandView.Margin.Thickness = new (1, 0, 1, 0);
+            _commandView.Margin.Thickness = GetMarginThickness ();
 
             _commandView.HotKeyChanged += (s, e) =>
                                           {
@@ -364,7 +397,6 @@ public class Shortcut : View
             _commandView.HotKeySpecifier = new ('_');
 
             Title = _commandView.Text;
-            _commandView.TextChanged += CommandViewTextChanged;
 
             SetHelpViewDefaultLayout ();
             SetKeyViewDefaultLayout ();
@@ -373,8 +405,6 @@ public class Shortcut : View
 
             return;
 
-            void CommandViewMouseEvent (object sender, MouseEventEventArgs e) { e.Handled = true; }
-
             void CommandViewTextChanged (object sender, StateEventArgs<string> e)
             {
                 Title = _commandView.Text;
@@ -417,11 +447,12 @@ public class Shortcut : View
 
     private void SetHelpViewDefaultLayout ()
     {
-        HelpView.Margin.Thickness = new (1, 0, 1, 0);
+        HelpView.Margin.Thickness = GetMarginThickness ();
         HelpView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
         HelpView.Y = 0; //Pos.Center (),    
         HelpView.Width = Dim.Auto (DimAutoStyle.Text);
-        HelpView.Height = Dim.Height (CommandView);
+        HelpView.Height = CommandView?.IsAdded == true ? Dim.Height (CommandView) : 1;
+
         HelpView.Visible = true;
         HelpView.VerticalTextAlignment = Alignment.Center;
     }
@@ -537,12 +568,12 @@ public class Shortcut : View
 
     private void SetKeyViewDefaultLayout ()
     {
-        KeyView.Margin.Thickness = new (1, 0, 1, 0);
+        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));
-        KeyView.Height = Dim.Height (CommandView);
+        KeyView.Height = CommandView?.IsAdded == true ? Dim.Height (CommandView) : 1;
+
         KeyView.Visible = true;
 
         // Right align the text in the keyview
@@ -582,6 +613,7 @@ public class Shortcut : View
         switch (KeyBindingScope)
         {
             case KeyBindingScope.Application:
+                handled = false;
                 break;
 
             case KeyBindingScope.Focused:
@@ -663,18 +695,9 @@ public class Shortcut : View
     /// <inheritdoc/>
     public override bool OnLeave (View view)
     {
+        // Reset the color scheme (to SuperView).
         ColorScheme = null;
 
-        return base.OnLeave (view);
-        if (SuperView is { })
-        {
-            ColorScheme = new (SuperView?.ColorScheme)
-            {
-                Normal = SuperView.ColorScheme.Normal,
-                HotNormal = SuperView.ColorScheme.HotNormal
-            };
-        }
-
         return base.OnLeave (view);
     }
 

+ 203 - 63
UICatalog/Scenarios/Shortcuts.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.ObjectModel;
 using System.Linq;
+using System.Timers;
 using Terminal.Gui;
 
 namespace UICatalog.Scenarios;
@@ -34,15 +35,16 @@ public class Shortcuts : Scenario
         {
             X = Pos.AnchorEnd (),
             Width = 40,
-            Height = Dim.Fill (),
+            Height = Dim.Fill (4),
             ColorScheme = Colors.ColorSchemes ["Toplevel"],
             Source = new ListWrapper<string> (eventSource)
         };
         Application.Top.Add (eventLog);
 
-        var shortcut1 = new Shortcut
+        var vShortcut1 = new Shortcut
         {
-            X = 20,
+            Orientation = Orientation.Vertical,
+            X = 0,
             Width = 35,
             Title = "A_pp Shortcut",
             Key = Key.F1,
@@ -50,14 +52,15 @@ public class Shortcuts : Scenario
             KeyBindingScope = KeyBindingScope.Application,
             BorderStyle = LineStyle.Dotted
         };
-        shortcut1.Border.Thickness = new (1, 1, 1, 1);
-        Application.Top.Add (shortcut1);
+        vShortcut1.Border.Thickness = new (1, 1, 1, 1);
+        Application.Top.Add (vShortcut1);
 
-        var shortcut2 = new Shortcut
+        var vShortcut2 = new Shortcut
         {
-            X = 20,
-            Y = Pos.Bottom (shortcut1) - 1,
-            Width = Dim.Width (shortcut1),
+            Orientation = Orientation.Vertical,
+            X = 0,
+            Y = Pos.Bottom (vShortcut1) - 1,
+            Width = Dim.Width (vShortcut1),
             Key = Key.F2,
             Text = "Width is ^",
             KeyBindingScope = KeyBindingScope.HotKey,
@@ -69,71 +72,73 @@ public class Shortcuts : Scenario
             }
         };
 
-        ((RadioGroup)shortcut2.CommandView).SelectedItemChanged += (o, args) =>
+        ((RadioGroup)vShortcut2.CommandView).SelectedItemChanged += (o, args) =>
                                                                    {
                                                                        eventSource.Add ($"SelectedItemChanged: {o.GetType ().Name} - {args.SelectedItem}");
                                                                        eventLog.MoveDown ();
                                                                    };
 
-        shortcut2.Accept += (o, args) =>
+        vShortcut2.Accept += (o, args) =>
                             {
                                 // Cycle to next item. If at end, set 0
-                                if (((RadioGroup)shortcut2.CommandView).SelectedItem < ((RadioGroup)shortcut2.CommandView).RadioLabels.Length - 1)
+                                if (((RadioGroup)vShortcut2.CommandView).SelectedItem < ((RadioGroup)vShortcut2.CommandView).RadioLabels.Length - 1)
                                 {
-                                    ((RadioGroup)shortcut2.CommandView).SelectedItem++;
+                                    ((RadioGroup)vShortcut2.CommandView).SelectedItem++;
                                 }
                                 else
                                 {
-                                    ((RadioGroup)shortcut2.CommandView).SelectedItem = 0;
+                                    ((RadioGroup)vShortcut2.CommandView).SelectedItem = 0;
                                 }
                             };
-        shortcut2.Border.Thickness = new (1, 1, 1, 1);
-        Application.Top.Add (shortcut2);
+        vShortcut2.Border.Thickness = new (1, 1, 1, 1);
+        Application.Top.Add (vShortcut2);
 
-        var shortcut3 = new Shortcut
+        var vShortcut3 = new Shortcut
         {
-            X = 20,
-            Y = Pos.Bottom (shortcut2),
+            Orientation = Orientation.Vertical,
+            X = 0,
+            Y = Pos.Bottom (vShortcut2),
             CommandView = new CheckBox { Text = "_Align" },
             Key = Key.F3,
             HelpText = "Width is Fill",
             Width = Dim.Fill () - Dim.Width (eventLog),
             KeyBindingScope = KeyBindingScope.HotKey,
-            BorderStyle = LineStyle.Dotted
+            BorderStyle = LineStyle.Rounded
         };
-        shortcut3.CommandView.CanFocus = true;
-        shortcut3.Border.Thickness = new (1, 1, 1, 0);
+        vShortcut3.Border.Thickness = new (1, 1, 1, 0);
 
-        ((CheckBox)shortcut3.CommandView).Toggled += (s, e) =>
+        ((CheckBox)vShortcut3.CommandView).Toggled += (s, e) =>
                                                      {
-                                                         if (shortcut3.CommandView is CheckBox cb)
+                                                         if (vShortcut3.CommandView is CheckBox cb)
                                                          {
                                                              eventSource.Add ($"Toggled: {cb.Text}");
                                                              eventLog.MoveDown ();
 
                                                              var max = 0;
+                                                             var toAlign = Application.Top.Subviews.Where (v => v is Shortcut s && s.Orientation == Orientation.Vertical && s.BorderStyle == LineStyle.Rounded);
 
                                                              if (e.NewValue == true)
                                                              {
-                                                                 foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!)
+                                                                 foreach (Shortcut peer in toAlign)
                                                                  {
                                                                      max = Math.Max (max, peer.KeyView.Text.GetColumns ());
                                                                  }
                                                              }
 
-                                                             foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!)
+                                                             foreach (Shortcut peer in toAlign)
                                                              {
                                                                  peer.MinimumKeyViewSize = max;
                                                              }
                                                          }
                                                      };
-        Application.Top.Add (shortcut3);
+        Application.Top.Add (vShortcut3);
 
-        var shortcut4 = new Shortcut
+        var vShortcut4 = new Shortcut
         {
-            X = 20,
-            Y = Pos.Bottom (shortcut3),
-            Width = Dim.Width (shortcut3),
+            Orientation = Orientation.Vertical,
+            X = 0,
+            Y = Pos.Bottom (vShortcut3),
+            Width = Dim.Width (vShortcut3),
             CommandView = new Button
             {
                 Title = "B_utton",
@@ -141,41 +146,56 @@ public class Shortcuts : Scenario
             HelpText = "Width is Fill",
             Key = Key.K,
             KeyBindingScope = KeyBindingScope.HotKey,
-            BorderStyle = LineStyle.Dotted
+            BorderStyle = LineStyle.Rounded
         };
-        Button button = (Button)shortcut4.CommandView;
-        shortcut4.CommandView.Accept += Button_Clicked;
-        shortcut4.CommandView.CanFocus = true;
-        shortcut4.Border.Thickness = new (1, 0, 1,0);
+        Button button = (Button)vShortcut4.CommandView;
+        vShortcut4.CommandView.Accept += Button_Clicked;
+        vShortcut4.Border.Thickness = new (1, 0, 1, 0);
 
-        Application.Top.Add (shortcut4);
+        Application.Top.Add (vShortcut4);
 
-        var shortcut5 = new Shortcut
+        var vShortcut5 = new Shortcut
         {
-            X = 20,
-            Y = Pos.Bottom (shortcut4) ,
-            Width = Dim.Width (shortcut4),
+            Orientation = Orientation.Vertical,
+            X = 0,
+            Y = Pos.Bottom (vShortcut4),
+            Width = Dim.Width (vShortcut4),
 
-            Title = "Fi_ve",
             Key = Key.F5.WithCtrl.WithAlt.WithShift,
-            HelpText = "Width is Fill",
+            HelpText = "CommandView.CanFocus",
             KeyBindingScope = KeyBindingScope.HotKey,
-            BorderStyle = LineStyle.Dotted
+            BorderStyle = LineStyle.Rounded,
+            CommandView = new CheckBox { Text = "_CanFocus" },
         };
-        shortcut5.Border.Thickness = new (1, 0, 1, 1);
+        vShortcut5.Border.Thickness = new (1, 0, 1, 1);
 
-        Application.Top.Add (shortcut5);
+        ((CheckBox)vShortcut5.CommandView).Toggled += (s, e) =>
+                                                     {
+                                                         if (vShortcut5.CommandView is CheckBox cb)
+                                                         {
+                                                             eventSource.Add ($"Toggled: {cb.Text}");
+                                                             eventLog.MoveDown ();
+
+                                                             foreach (Shortcut peer in Application.Top.Subviews.Where (v => v is Shortcut)!)
+                                                             {
+                                                                 peer.CanFocus = e.NewValue == true;
+                                                                 peer.CommandView.CanFocus = e.NewValue == true;
+                                                             }
+                                                         }
+                                                     };
+        Application.Top.Add (vShortcut5);
 
-        var shortcutSlider = new Shortcut
+        var vShortcutSlider = new Shortcut
         {
-            X = 20,
-            Y = Pos.Bottom (shortcut5) - 1,
+            Orientation = Orientation.Vertical,
+            X = 0,
+            Y = Pos.Bottom (vShortcut5) - 1,
             Key = Key.F5,
             HelpText = "Width is Fill",
-            Width = Dim.Width (shortcut5),
+            Width = Dim.Width (vShortcut5),
 
             KeyBindingScope = KeyBindingScope.HotKey,
-            BorderStyle = LineStyle.Dotted,
+            BorderStyle = LineStyle.Rounded,
             CommandView = new Slider<string>
             {
                 Orientation = Orientation.Vertical,
@@ -183,31 +203,151 @@ public class Shortcuts : Scenario
             }
         };
 
-        ((Slider<string>)shortcutSlider.CommandView).Options = new () { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } };
-        ((Slider<string>)shortcutSlider.CommandView).SetOption (0);
-        shortcutSlider.Border.Thickness = new (1, 1, 1, 1);
+        ((Slider<string>)vShortcutSlider.CommandView).Options = new () { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } };
+        ((Slider<string>)vShortcutSlider.CommandView).SetOption (0);
+        vShortcutSlider.Border.Thickness = new (1, 1, 1, 1);
 
-        ((Slider<string>)shortcutSlider.CommandView).OptionsChanged += (o, args) =>
+        ((Slider<string>)vShortcutSlider.CommandView).OptionsChanged += (o, args) =>
                                                                        {
                                                                            eventSource.Add ($"OptionsChanged: {o.GetType ().Name} - {args.Options}");
                                                                            eventLog.MoveDown ();
                                                                        };
 
-        Application.Top.Add (shortcutSlider);
+        Application.Top.Add (vShortcutSlider);
 
-        var shortcut6 = new Shortcut
+        var vShortcut6 = new Shortcut
         {
-            X = 20,
-            Y = Pos.Bottom (shortcutSlider) - 1,
-            Width = Dim.Width (shortcutSlider),
+            Orientation = Orientation.Vertical,
+            X = 0,
+            Y = Pos.Bottom (vShortcutSlider) - 1,
+            Width = Dim.Width (vShortcutSlider),
 
             Title = "_No Key",
             HelpText = "Keyless",
-            BorderStyle = LineStyle.Dotted
+            BorderStyle = LineStyle.Rounded
+        };
+        vShortcut6.Border.Thickness = new (1, 1, 1, 1);
+
+        Application.Top.Add (vShortcut6);
+
+        ((CheckBox)vShortcut3.CommandView).OnToggled();
+
+        // Horizontal
+        var hShortcut1 = new Shortcut
+        {
+            X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
+            Y = Pos.Bottom (eventLog) + 1,
+            Key = Key.F7,
+            HelpText = "Horizontal",
+            BorderStyle = LineStyle.Dashed,
+            CanFocus = false
+        };
+        hShortcut1.Border.Thickness = new (0, 0, 1, 0);
+
+        hShortcut1.CommandView = new ProgressBar
+        {
+            Text = "Progress",
+            Title = "P",
+            Fraction = 0.5f,
+            Width = 10,
+            Height = 1,
+            ProgressBarStyle = ProgressBarStyle.Continuous
+        };
+        hShortcut1.CommandView.Width = 10;
+        hShortcut1.CommandView.Height = 1;
+        hShortcut1.CommandView.CanFocus = false;
+        Timer timer = new (10)
+        {
+            AutoReset = true,
+        };
+        timer.Elapsed += (o, args) =>
+                         {
+                             if (hShortcut1.CommandView is ProgressBar pb)
+                             {
+                                 if (pb.Fraction == 1.0)
+                                 {
+                                     pb.Fraction = 0;
+                                 }
+                                 pb.Fraction += 0.01f;
+
+                                 Application.Wakeup ();
+
+                                 pb.SetNeedsDisplay ();
+                             }
+                         };
+        timer.Start ();
+
+        Application.Top.Add (hShortcut1);
+
+        var textField = new TextField ()
+        {
+            Text = "Edit me",
+            Width = 10,
+            Height = 1,
+            CanFocus = true
+        };
+
+        var hShortcut2 = new Shortcut
+        {
+            X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
+            Y = Pos.Top (hShortcut1),
+            Key = Key.F8,
+            HelpText = "Edit",
+            CanFocus = true,
+            BorderStyle = LineStyle.Dashed,
+            CommandView = textField,
+        };
+        hShortcut2.Border.Thickness = new (0, 0, 1, 0);
+
+        Application.Top.Add (hShortcut2);
+
+        var hShortcutBG = new Shortcut
+        {
+            X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1)-1,
+            Y = Pos.Top (hShortcut2),
+            Key = Key.F9,
+            HelpText = "BG Color",
+            BorderStyle = LineStyle.Dashed,
+            CanFocus = false
+        };
+
+        var bgColor = new ColorPicker ()
+        {
+            CanFocus = false,
+            BoxHeight = 1,
+            BoxWidth = 1,
         };
-        shortcut6.Border.Thickness = new (1, 1, 1, 1);
+        bgColor.ColorChanged += (o, args) =>
+                                {
+                                    Application.Top.ColorScheme = new ColorScheme (Application.Top.ColorScheme)
+                                    {
+                                        Normal = new Attribute (Application.Top.ColorScheme.Normal.Foreground, args.Color),
+                                    };
+                                };
+        hShortcutBG.CommandView = bgColor;
+        hShortcutBG.Border.Thickness = new (1, 0, 1, 0);
+
+        Application.Top.Add (hShortcutBG);
+
+        var hShortcut3 = new Shortcut
+        {
+            X = Pos.Align (Alignment.Start, AlignmentModes.IgnoreFirstOrLast, 1),
+            Y = Pos.Top (hShortcut2),
+            Key = Key.Esc,
+            KeyBindingScope = KeyBindingScope.Application,
+            Title = "Quit",
+            HelpText = "App Scope",
+            BorderStyle = LineStyle.Dashed,
+            CanFocus = false
+        };
+        hShortcut3.Border.Thickness = new (0);
+        hShortcut3.Accept += (o, args) =>
+                            {
+                                Application.RequestStop ();
+                            };
+
+        Application.Top.Add (hShortcut3);
 
-        Application.Top.Add (shortcut6);
 
         foreach (View sh in Application.Top.Subviews.Where (v => v is Shortcut)!)
         {