Browse Source

Reworked Shortcut

Tig 1 year ago
parent
commit
9612d7fbb9

+ 45 - 43
Terminal.Gui/View/Layout/DimAuto.cs

@@ -151,49 +151,49 @@ public class DimAuto () : Dim
                 subviewsSize += maxAnchorEnd;
                 subviewsSize += maxAnchorEnd;
                 #endregion Anchored
                 #endregion Anchored
 
 
-                #region Aligned
+                //#region Aligned
 
 
-                // Now, handle subviews that are anchored to the end
-                // [x] PosAnchorEnd
-                int maxAlign = 0;
-                if (dimension == Dimension.Width)
-                {
-                    // Use Linq to get a list of distinct GroupIds from the subviews
-                    List<int> groupIds = includedSubviews.Select (v => v.X is PosAlign posAlign ? posAlign.GroupId : -1).Distinct ().ToList ();
-
-                    foreach (var groupId in groupIds)
-                    {
-                        List<int> dimensionsList = new ();
-
-                        // PERF: If this proves a perf issue, consider caching a ref to this list in each item
-                        List<PosAlign?> posAlignsInGroup = includedSubviews.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
-                                };
-                            })
-                            .Select (v => dimension == Dimension.Width ? v.X as PosAlign : v.Y as PosAlign)
-                            .ToList ();
-
-                        if (posAlignsInGroup.Count == 0)
-                        {
-                            continue;
-                        }
-
-                        maxAlign = posAlignsInGroup [0].CalculateMinDimension (groupId, includedSubviews, dimension);
-                    }
-                }
-                else
-                {
-                    subviews = includedSubviews.Where (v => v.Y is PosAlign).ToList ();
-                }
+                //// Now, handle subviews that are anchored to the end
+                //// [x] PosAnchorEnd
+                //int maxAlign = 0;
+                //if (dimension == Dimension.Width)
+                //{
+                //    // Use Linq to get a list of distinct GroupIds from the subviews
+                //    List<int> groupIds = includedSubviews.Select (v => v.X is PosAlign posAlign ? posAlign.GroupId : -1).Distinct ().ToList ();
+
+                //    foreach (var groupId in groupIds)
+                //    {
+                //        List<int> dimensionsList = new ();
+
+                //        // PERF: If this proves a perf issue, consider caching a ref to this list in each item
+                //        List<PosAlign?> posAlignsInGroup = includedSubviews.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
+                //                };
+                //            })
+                //            .Select (v => dimension == Dimension.Width ? v.X as PosAlign : v.Y as PosAlign)
+                //            .ToList ();
+
+                //        if (posAlignsInGroup.Count == 0)
+                //        {
+                //            continue;
+                //        }
+
+                //        maxAlign = PosAlign.CalculateMinDimension (groupId, includedSubviews, dimension);
+                //    }
+                //}
+                //else
+                //{
+                //    subviews = includedSubviews.Where (v => v.Y is PosAlign).ToList ();
+                //}
 
 
-                subviewsSize = int.Max (subviewsSize, maxAlign);
-                #endregion Aligned
+                //subviewsSize = int.Max (subviewsSize, maxAlign);
+                //#endregion Aligned
 
 
 
 
                 #region Auto
                 #region Auto
@@ -295,9 +295,11 @@ public class DimAuto () : Dim
         // And, if min: is set, it wins if larger
         // And, if min: is set, it wins if larger
         max = int.Max (max, autoMin);
         max = int.Max (max, autoMin);
 
 
+        // And, if max: is set, it wins if smaller
+        max = int.Min (max, autoMax);
+
         // Factor in adornments
         // Factor in adornments
         Thickness thickness = us.GetAdornmentsThickness ();
         Thickness thickness = us.GetAdornmentsThickness ();
-
         max += dimension switch
         max += dimension switch
         {
         {
             Dimension.Width => thickness.Horizontal,
             Dimension.Width => thickness.Horizontal,
@@ -306,7 +308,7 @@ public class DimAuto () : Dim
             _ => throw new ArgumentOutOfRangeException (nameof (dimension), dimension, null)
             _ => throw new ArgumentOutOfRangeException (nameof (dimension), dimension, null)
         };
         };
 
 
-        return int.Min (max, autoMax);
+        return max;
     }
     }
 
 
     internal override bool ReferencesOtherViews ()
     internal override bool ReferencesOtherViews ()

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

@@ -168,7 +168,7 @@ public class PosAlign : Pos
         return 0;
         return 0;
     }
     }
 
 
-    internal int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension)
+    public static int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension)
     {
     {
         List<int> dimensionsList = new ();
         List<int> dimensionsList = new ();
 
 
@@ -217,6 +217,6 @@ public class PosAlign : Pos
         aligner.ContainerSize = dimensionsList.Sum();
         aligner.ContainerSize = dimensionsList.Sum();
         int [] locations = aligner.Align (dimensionsList.ToArray ());
         int [] locations = aligner.Align (dimensionsList.ToArray ());
 
 
-        return locations.Sum ();
+        return dimensionsList.Sum ();
     }
     }
 }
 }

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

@@ -717,6 +717,12 @@ public partial class View
                     return true;
                     return true;
                 }
                 }
             }
             }
+
+            bool recurse = subview.ProcessSubViewKeyBindings (keyEvent, ref handled);
+            if (recurse || (handled is { } && (bool)handled))
+            {
+                return true;
+            }
         }
         }
 
 
         return false;
         return false;
@@ -871,7 +877,7 @@ public partial class View
     /// <param name="f">The function.</param>
     /// <param name="f">The function.</param>
     protected void AddCommand (Command command, Func<bool?> f)
     protected void AddCommand (Command command, Func<bool?> f)
     {
     {
-        CommandImplementations [command] = ctx => f (); ;
+        CommandImplementations [command] = ctx => f ();
     }
     }
 
 
     /// <summary>Returns all commands that are supported by this <see cref="View"/>.</summary>
     /// <summary>Returns all commands that are supported by this <see cref="View"/>.</summary>

+ 60 - 44
Terminal.Gui/Views/Shortcut.cs

@@ -34,35 +34,23 @@ namespace Terminal.Gui;
 /// </remarks>
 /// </remarks>
 public class Shortcut : View
 public class Shortcut : View
 {
 {
-    // Hosts the Command, Help, and Key Views. Needed (IIRC - wrote a long time ago) to allow mouse clicks to be handled by the Shortcut.
-    internal readonly View _container;
-
     /// <summary>
     /// <summary>
     ///     Creates a new instance of <see cref="Shortcut"/>.
     ///     Creates a new instance of <see cref="Shortcut"/>.
     /// </summary>
     /// </summary>
     public Shortcut ()
     public Shortcut ()
     {
     {
+        Id= "_shortcut";
+        HighlightStyle = HighlightStyle.Pressed;
+        Highlight += Shortcut_Highlight;
         CanFocus = true;
         CanFocus = true;
-        Width = Dim.Auto (DimAutoStyle.Content);
-        Height = Dim.Auto (DimAutoStyle.Content);
-
-        //Height = Dim.Auto (minimumContentDim: 1, maximumContentDim: 1);
+        Width = Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width)));
+        Height = Dim.Auto (DimAutoStyle.Content, minimumContentDim: 1);
 
 
-        AddCommand (Gui.Command.HotKey, () => true);
+        AddCommand (Gui.Command.HotKey, OnAccept);
         AddCommand (Gui.Command.Accept, OnAccept);
         AddCommand (Gui.Command.Accept, OnAccept);
         KeyBindings.Add (KeyCode.Space, Gui.Command.Accept);
         KeyBindings.Add (KeyCode.Space, Gui.Command.Accept);
         KeyBindings.Add (KeyCode.Enter, Gui.Command.Accept);
         KeyBindings.Add (KeyCode.Enter, Gui.Command.Accept);
 
 
-        _container = new ()
-        {
-            Id = "_container",
-            // Only the Shortcut (_container) should be able to have focus, not any subviews.
-            CanFocus = true,
-            Width = Dim.Auto (DimAutoStyle.Content, 1),
-            Height = Dim.Auto (DimAutoStyle.Content, 1),
-            BorderStyle = LineStyle.Dashed
-        };
-
         CommandView = new ();
         CommandView = new ();
 
 
         HelpView = new ()
         HelpView = new ()
@@ -70,15 +58,15 @@ public class Shortcut : View
             Id = "_helpView",
             Id = "_helpView",
             // Only the Shortcut should be able to have focus, not any subviews
             // Only the Shortcut should be able to have focus, not any subviews
             CanFocus = false,
             CanFocus = false,
-            X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast | AlignmentModes.AddSpaceBetweenItems),
-            Y = Pos.Center (),
+            X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast),
+            Y = 0,//Pos.Center (),
 
 
             // Helpview is the only subview that doesn't have a min width
             // Helpview is the only subview that doesn't have a min width
             Width = Dim.Auto (DimAutoStyle.Text),
             Width = Dim.Auto (DimAutoStyle.Text),
             Height = Dim.Auto (DimAutoStyle.Text),
             Height = Dim.Auto (DimAutoStyle.Text),
-            ColorScheme = Colors.ColorSchemes ["Error"]
         };
         };
-        _container.Add (HelpView);
+        HelpView.Margin.Thickness = new Thickness (1, 0, 1, 0);
+        Add (HelpView);
 
 
         //        HelpView.TextAlignment = Alignment.End;
         //        HelpView.TextAlignment = Alignment.End;
         HelpView.MouseClick += Shortcut_MouseClick;
         HelpView.MouseClick += Shortcut_MouseClick;
@@ -88,28 +76,24 @@ public class Shortcut : View
             Id = "_keyView",
             Id = "_keyView",
             // Only the Shortcut should be able to have focus, not any subviews
             // Only the Shortcut should be able to have focus, not any subviews
             CanFocus = false,
             CanFocus = false,
-            X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast | AlignmentModes.AddSpaceBetweenItems),
-            Y = Pos.Center (),
+            X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast),
+            Y = 0,//Pos.Center (),
 
 
             // Bar will set the width of all KeyViews to the width of the widest KeyView.
             // Bar will set the width of all KeyViews to the width of the widest KeyView.
             Width = Dim.Auto (DimAutoStyle.Text),
             Width = Dim.Auto (DimAutoStyle.Text),
             Height = Dim.Auto (DimAutoStyle.Text),
             Height = Dim.Auto (DimAutoStyle.Text),
         };
         };
-        _container.Add (KeyView);
+        KeyView.Margin.Thickness = new Thickness (1, 0, 1, 0);
+        Add (KeyView);
 
 
         KeyView.MouseClick += Shortcut_MouseClick;
         KeyView.MouseClick += Shortcut_MouseClick;
 
 
-        CommandView.Margin.Thickness = new Thickness (1, 0, 1, 0);
-        HelpView.Margin.Thickness = new Thickness (1, 0, 1, 0);
-        KeyView.Margin.Thickness = new Thickness (1, 0, 1, 0);
 
 
         MouseClick += Shortcut_MouseClick;
         MouseClick += Shortcut_MouseClick;
 
 
         TitleChanged += Shortcut_TitleChanged;
         TitleChanged += Shortcut_TitleChanged;
         Initialized += OnInitialized;
         Initialized += OnInitialized;
 
 
-        Add (_container);
-
         return;
         return;
 
 
         void OnInitialized (object sender, EventArgs e)
         void OnInitialized (object sender, EventArgs e)
@@ -126,6 +110,36 @@ public class Shortcut : View
         }
         }
     }
     }
 
 
+    private Color? _savedForeColor;
+
+    private void Shortcut_Highlight (object sender, HighlightEventArgs e)
+    {
+        if (e.HighlightStyle.HasFlag (HighlightStyle.Pressed))
+        {
+            if (!_savedForeColor.HasValue)
+            {
+                _savedForeColor = ColorScheme.Normal.Foreground;
+            }
+
+            ColorScheme cs = new ColorScheme (ColorScheme)
+            {
+                Normal = new Attribute (ColorScheme.Normal.Foreground.GetHighlightColor (), ColorScheme.Normal.Background)
+            };
+            ColorScheme = cs;
+        }
+
+        if (e.HighlightStyle == HighlightStyle.None && _savedForeColor.HasValue)
+        {
+            ColorScheme cs = new ColorScheme (ColorScheme)
+            {
+                Normal = new Attribute (_savedForeColor.Value, ColorScheme.Normal.Background)
+            };
+            ColorScheme = cs;
+        }
+        SuperView?.SetNeedsDisplay ();
+        e.Cancel = true;
+    }
+
     private void Shortcut_MouseClick (object sender, MouseEventEventArgs e)
     private void Shortcut_MouseClick (object sender, MouseEventEventArgs e)
     {
     {
         // When the Shortcut is clicked, we want to invoke the Command and Set focus
         // When the Shortcut is clicked, we want to invoke the Command and Set focus
@@ -253,7 +267,7 @@ public class Shortcut : View
 
 
             if (_commandView is { })
             if (_commandView is { })
             {
             {
-                _container.Remove (_commandView);
+                Remove (_commandView);
                 _commandView?.Dispose ();
                 _commandView?.Dispose ();
             }
             }
 
 
@@ -268,8 +282,8 @@ public class Shortcut : View
             // Bar will set the width of all CommandViews to the width of the widest CommandViews.
             // Bar will set the width of all CommandViews to the width of the widest CommandViews.
             _commandView.Width = Dim.Auto (DimAutoStyle.Text);
             _commandView.Width = Dim.Auto (DimAutoStyle.Text);
             _commandView.Height = Dim.Auto (DimAutoStyle.Text);
             _commandView.Height = Dim.Auto (DimAutoStyle.Text);
-            _commandView.X = X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast | AlignmentModes.AddSpaceBetweenItems);
-            _commandView.Y = Pos.Center ();
+            _commandView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
+            _commandView.Y = 0;//Pos.Center ();
 
 
             _commandView.MouseClick += Shortcut_MouseClick;
             _commandView.MouseClick += Shortcut_MouseClick;
             _commandView.Accept += CommandView_Accept;
             _commandView.Accept += CommandView_Accept;
@@ -287,11 +301,11 @@ public class Shortcut : View
 
 
             _commandView.HotKeySpecifier = new ('_');
             _commandView.HotKeySpecifier = new ('_');
 
 
-            _container.Remove (HelpView);
-            _container.Remove (KeyView);
-            _container.Add (_commandView, HelpView, KeyView);
+            Remove (HelpView);
+            Remove (KeyView);
+            Add (_commandView, HelpView, KeyView);
 
 
-            UpdateKeyBinding();
+            UpdateKeyBinding ();
 
 
         }
         }
     }
     }
@@ -319,6 +333,8 @@ public class Shortcut : View
         {
         {
             e.Cancel = args.Handled;
             e.Cancel = args.Handled;
         }
         }
+
+        e.Cancel = true;
     }
     }
 
 
     #endregion Command
     #endregion Command
@@ -406,7 +422,7 @@ public class Shortcut : View
     {
     {
         if (KeyBindingScope == KeyBindingScope.Application)
         if (KeyBindingScope == KeyBindingScope.Application)
         {
         {
-          //  return;
+            //  return;
         }
         }
 
 
         if (Command != null && Key != null && Key != Key.Empty)
         if (Command != null && Key != null && Key != Key.Empty)
@@ -420,7 +436,7 @@ public class Shortcut : View
             }
             }
             else
             else
             {
             {
-               // throw new InvalidOperationException ($"CommandView does not support the command {Command.Value}");
+                // throw new InvalidOperationException ($"CommandView does not support the command {Command.Value}");
             }
             }
         }
         }
     }
     }
@@ -480,7 +496,7 @@ public class Shortcut : View
             handled = args.Handled;
             handled = args.Handled;
         }
         }
 
 
-        return handled;
+        return true;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
@@ -493,14 +509,14 @@ public class Shortcut : View
             HotNormal = ColorScheme.HotFocus
             HotNormal = ColorScheme.HotFocus
         };
         };
 
 
-        _container.ColorScheme = cs;
+        // _container.ColorScheme = cs;
 
 
         cs = new (ColorScheme)
         cs = new (ColorScheme)
         {
         {
             Normal = ColorScheme.HotFocus,
             Normal = ColorScheme.HotFocus,
             HotNormal = ColorScheme.Focus
             HotNormal = ColorScheme.Focus
         };
         };
-        KeyView.ColorScheme = cs;
+        //KeyView.ColorScheme = cs;
 
 
         return base.OnEnter (view);
         return base.OnEnter (view);
     }
     }
@@ -515,14 +531,14 @@ public class Shortcut : View
             HotNormal = ColorScheme.HotNormal
             HotNormal = ColorScheme.HotNormal
         };
         };
 
 
-        _container.ColorScheme = cs;
+        //   _container.ColorScheme = cs;
 
 
         cs = new (ColorScheme)
         cs = new (ColorScheme)
         {
         {
             Normal = ColorScheme.HotNormal,
             Normal = ColorScheme.HotNormal,
             HotNormal = ColorScheme.Normal
             HotNormal = ColorScheme.Normal
         };
         };
-        KeyView.ColorScheme = cs;
+        //KeyView.ColorScheme = cs;
 
 
         return base.OnLeave (view);
         return base.OnLeave (view);
     }
     }

+ 106 - 0
UICatalog/Scenarios/Shortcuts.cs

@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Text;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios;
+
+[ScenarioMetadata ("Shortcuts", "Illustrates Shortcut class.")]
+[ScenarioCategory ("Controls")]
+public class Shortcuts : Scenario
+{
+    public override void Main ()
+    {
+        Application.Init ();
+        Window app = new ();
+
+        app.Loaded += App_Loaded;
+
+        Application.Run (app);
+        app.Dispose ();
+        Application.Shutdown ();
+    }
+
+
+    // Setting everything up in Loaded handler because we change the
+    // QuitKey and it only sticks if changed after init
+    private void App_Loaded (object sender, EventArgs e)
+    {
+        Application.QuitKey = Key.Z.WithCtrl;
+        Application.Top.Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}";
+
+        ObservableCollection<string> eventSource = new ();
+        ListView eventLog = new ListView ()
+        {
+            X = Pos.AnchorEnd (),
+            Width = 50,
+            Height = Dim.Fill (),
+            ColorScheme = Colors.ColorSchemes ["Toplevel"],
+            Source = new ListWrapper<string> (eventSource)
+        };
+        Application.Top.Add (eventLog);
+
+        var shortcut1 = new Shortcut
+        {
+            Title = "Zi_gzag",
+            Key = Key.F1,
+            Text = "Gonna zig zag",
+            KeyBindingScope = KeyBindingScope.HotKey,
+            Command = Command.Accept,
+            BorderStyle = LineStyle.Dotted
+        };  
+        shortcut1.Border.Thickness = new Thickness (1, 0, 1, 0);
+        shortcut1.Accept += (s, e) =>
+                            {
+                                eventSource.Add ($"Accept: {s}");
+                                eventLog.MoveDown ();
+                            };
+        Application.Top.Add (shortcut1);
+
+        var shortcut2 = new Shortcut
+        {
+            Y = Pos.Bottom (shortcut1),
+            Width = Dim.Width(shortcut1),
+            Title = "_Two",
+            Key = Key.F2.WithAlt,
+            Text = "Number two",
+            KeyBindingScope = KeyBindingScope.HotKey,
+            Command = Command.Accept,
+            BorderStyle = LineStyle.Dotted
+        };
+        shortcut2.Border.Thickness = new Thickness (1, 0, 1, 0);
+        shortcut2.Accept += (s, e) =>
+                            {
+                                eventSource.Add ($"Accept: {s}");
+                                eventLog.MoveDown ();
+                            };
+        Application.Top.Add (shortcut2);
+
+        var shortcut3 = new Shortcut
+        {
+            Y = Pos.Bottom (shortcut2),
+            Width = Dim.Width (shortcut1),
+            Title = "T_hree",
+            Key = Key.F3,
+            Text = "Number 3",
+            KeyBindingScope = KeyBindingScope.HotKey,
+            Command = Command.Accept,
+            BorderStyle = LineStyle.Dotted
+        };
+        shortcut3.Border.Thickness = new Thickness (1, 0, 1, 0);
+
+        shortcut3.Accept += (s, e) =>
+                            {
+                                eventSource.Add ($"Accept: {s}");
+                                eventLog.MoveDown ();
+                            };
+        Application.Top.Add (shortcut3);
+
+        shortcut1.SetFocus ();
+
+    }
+
+    private void Button_Clicked (object sender, EventArgs e) { MessageBox.Query ("Hi", $"You clicked {sender}"); }
+
+}