Преглед изворни кода

Enabled CanFocus for COmmandView

Tig пре 1 година
родитељ
комит
2a3808a7c0
2 измењених фајлова са 164 додато и 136 уклоњено
  1. 134 120
      Terminal.Gui/Views/Shortcut.cs
  2. 30 16
      UICatalog/Scenarios/Shortcuts.cs

+ 134 - 120
Terminal.Gui/Views/Shortcut.cs

@@ -7,7 +7,8 @@ namespace Terminal.Gui;
 // TODO: I tried `BarItem` but that's not great either as it implies it can only be used in `Bar`s.
 
 /// <summary>
-///     Displays a command, help text, and a key binding. When the key is pressed, the command will be invoked. Useful for displaying a command in <see cref="Bar"/> such as a
+///     Displays a command, help text, and a key binding. When the key is pressed, the command will be invoked. Useful for
+///     displaying a command in <see cref="Bar"/> such as a
 ///     menu, toolbar, or status bar.
 /// </summary>
 /// <remarks>
@@ -17,14 +18,17 @@ namespace Terminal.Gui;
 ///         <see cref="Accept"/> event to be fired
 ///     </para>
 ///     <para>
-///         If <see cref="KeyBindingScope"/> is <see cref="KeyBindingScope.Application"/>, the <see cref="Command.Accept"/> command 
+///         If <see cref="KeyBindingScope"/> is <see cref="KeyBindingScope.Application"/>, the <see cref="Command.Accept"/>
+///         command
 ///         be invoked regardless of what View has focus, enabling an application-wide keyboard shortcut.
 ///     </para>
 ///     <para>
-///         A Shortcut displays the command text on the left side, the help text in the middle, and the key binding on the right side.
+///         A Shortcut displays the command text on the left side, the help text in the middle, and the key binding on the
+///         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 or by setting
+///         <see cref="View.Title"/>.
 ///     </para>
 ///     <para>
 ///         The help text can be set by setting the <see cref="HelpText"/> property or by setting <see cref="View.Text"/>.
@@ -48,28 +52,23 @@ public class Shortcut : View
         Width = GetWidthDimAuto ();
         Height = Dim.Auto (DimAutoStyle.Content, 1);
 
-        AddCommand (Gui.Command.HotKey, OnAccept);
-        AddCommand (Gui.Command.Accept, OnAccept);
-        KeyBindings.Add (KeyCode.Space, Gui.Command.Accept);
-        KeyBindings.Add (KeyCode.Enter, Gui.Command.Accept);
+        AddCommand (Command.HotKey, OnAccept);
+        AddCommand (Command.Accept, OnAccept);
+        KeyBindings.Add (KeyCode.Space, Command.Accept);
+        KeyBindings.Add (KeyCode.Enter, Command.Accept);
 
         TitleChanged += Shortcut_TitleChanged; // This needs to be set before CommandView is set
 
-        CommandView = new View ();
+        CommandView = new ();
 
         HelpView.Id = "_helpView";
         HelpView.CanFocus = false;
         SetHelpViewDefaultLayout ();
         Add (HelpView);
-
-        //        HelpView.TextAlignment = Alignment.End;
         HelpView.MouseClick += Shortcut_MouseClick;
 
         KeyView.Id = "_keyView";
-
-        // Only the Shortcut should be able to have focus, not any subviews
         KeyView.CanFocus = false;
-
         SetKeyViewDefaultLayout ();
         Add (KeyView);
 
@@ -85,14 +84,18 @@ public class Shortcut : View
 
         void OnInitialized (object sender, EventArgs e)
         {
+            SuperViewRendersLineCanvas = true;
+            Border.ShowTitle = false;
+
             ShowHide ();
 
             // Force Width to DimAuto to calculate natural width and then set it back
             Dim savedDim = Width;
             Width = GetWidthDimAuto ();
-            _naturalWidth = Frame.Width;
+            _minimumDimAutoWidth = Frame.Width;
             Width = savedDim;
 
+            // Set KeyView's colors to show "hot"
             if (ColorScheme != null)
             {
                 var cs = new ColorScheme (ColorScheme)
@@ -105,11 +108,11 @@ public class Shortcut : View
             }
         }
 
+        // Helper to set Width consistently
         Dim GetWidthDimAuto ()
         {
             return Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (() => PosAlign.CalculateMinDimension (0, Subviews, Dimension.Width)));
         }
-
     }
 
     // When one of the subviews is "empty" we don't want to show it. So we
@@ -118,27 +121,32 @@ public class Shortcut : View
     private void ShowHide ()
     {
         RemoveAll ();
+
         if (!string.IsNullOrEmpty (CommandView.Text))
         {
             Add (CommandView);
         }
+
         if (!string.IsNullOrEmpty (HelpView.Text))
         {
             Add (HelpView);
         }
+
         if (Key != Key.Empty)
         {
             Add (KeyView);
         }
     }
 
-    private int? _naturalWidth;
+    // This is used to calculate the minimum width of the Shortcut when the width is NOT Dim.Auto
+    private int? _minimumDimAutoWidth;
 
+    // When layout starts, we need to adjust the layout of the HelpView and KeyView
     private void OnLayoutStarted (object sender, LayoutEventArgs e)
     {
         if (Width is DimAuto widthAuto)
         {
-            _naturalWidth = Frame.Width;
+            _minimumDimAutoWidth = Frame.Width;
         }
         else
         {
@@ -150,9 +158,9 @@ public class Shortcut : View
             int currentWidth = Frame.Width;
 
             // If our width is smaller than the natural then reduce width of HelpView.
-            if (currentWidth < _naturalWidth)
+            if (currentWidth < _minimumDimAutoWidth)
             {
-                int delta = _naturalWidth.Value - currentWidth;
+                int delta = _minimumDimAutoWidth.Value - currentWidth;
                 int maxHelpWidth = int.Max (0, HelpView.Text.GetColumns () + 2 - delta);
 
                 switch (maxHelpWidth)
@@ -235,6 +243,7 @@ public class Shortcut : View
     {
         // When the Shortcut is clicked, we want to invoke the Command and Set focus
         var view = sender as View;
+
         if (view != CommandView)
         {
             CommandView.InvokeCommand (Command.Accept);
@@ -263,34 +272,6 @@ public class Shortcut : View
         e.Handled = true;
     }
 
-    /// <inheritdoc/>
-    public override ColorScheme ColorScheme
-    {
-        get
-        {
-            if (base.ColorScheme == null)
-            {
-                return SuperView?.ColorScheme ?? base.ColorScheme;
-            }
-
-            return base.ColorScheme;
-        }
-        set
-        {
-            base.ColorScheme = value;
-
-            if (ColorScheme != null)
-            {
-                var cs = new ColorScheme (ColorScheme)
-                {
-                    Normal = ColorScheme.HotNormal,
-                    HotNormal = ColorScheme.Normal
-                };
-                KeyView.ColorScheme = cs;
-            }
-        }
-    }
-
     #region Command
 
     private View _commandView = new ();
@@ -386,7 +367,7 @@ public class Shortcut : View
             _commandView.TextChanged += CommandViewTextChanged;
 
             SetHelpViewDefaultLayout ();
-            SetKeyViewDefaultLayout();
+            SetKeyViewDefaultLayout ();
             ShowHide ();
             UpdateKeyBinding ();
 
@@ -440,10 +421,9 @@ public class Shortcut : View
         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 = Dim.Height (CommandView);
         HelpView.Visible = true;
         HelpView.VerticalTextAlignment = Alignment.Center;
-
     }
 
     /// <summary>
@@ -531,8 +511,8 @@ public class Shortcut : View
     public View KeyView { get; } = new ();
 
     private int _minimumKeyViewSize;
+
     /// <summary>
-    /// 
     /// </summary>
     public int MinimumKeyViewSize
     {
@@ -543,9 +523,10 @@ public class Shortcut : View
             {
                 //return;
             }
+
             _minimumKeyViewSize = value;
-            SetKeyViewDefaultLayout();
-            CommandView.SetNeedsLayout();
+            SetKeyViewDefaultLayout ();
+            CommandView.SetNeedsLayout ();
             HelpView.SetNeedsLayout ();
             KeyView.SetNeedsLayout ();
             SetSubViewNeedsDisplay ();
@@ -558,34 +539,31 @@ public class Shortcut : View
     {
         KeyView.Margin.Thickness = new (1, 0, 1, 0);
         KeyView.X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast);
+
         //KeyView.Y = Pos.Center ();
-        KeyView.Width = Dim.Auto (DimAutoStyle.Text, minimumContentDim: Dim.Func(GetMinimumKeyViewSize));
-        KeyView.Height = Dim.Height(CommandView);
+        KeyView.Width = Dim.Auto (DimAutoStyle.Text, Dim.Func (GetMinimumKeyViewSize));
+        KeyView.Height = Dim.Height (CommandView);
         KeyView.Visible = true;
+
         // Right align the text in the keyview
         KeyView.TextAlignment = Alignment.End;
         KeyView.VerticalTextAlignment = Alignment.Center;
+        KeyView.KeyBindings.Clear ();
     }
 
     private void UpdateKeyBinding ()
     {
-        if (KeyBindingScope == KeyBindingScope.Application)
-        {
-            //  return;
-        }
-
         if (Key != null)
         {
-            // CommandView holds our command/keybinding
-            // Add a key binding for this command to this Shortcut
-
-            CommandView.KeyBindings.Remove (Key);
-            CommandView.KeyBindings.Add (Key, KeyBindingScope, Command.Accept);
+            KeyBindings.Remove (Key);
+            KeyBindings.Add (Key, KeyBindingScope, Command.Accept);
         }
     }
 
     #endregion Key
 
+    #region Accept Handling
+
     /// <summary>
     ///     The event fired when the <see cref="Command.Accept"/> command is received. This
     ///     occurs if the user clicks on the Shortcut or presses <see cref="Key"/>.
@@ -599,39 +577,26 @@ public class Shortcut : View
     /// </summary>
     protected new bool? OnAccept ()
     {
-        // TODO: This is not completely thought through.
+        var handled = true;
 
-        if (Key == null || Key == Key.Empty)
+        switch (KeyBindingScope)
         {
-            return false;
-        }
-
-        var handled = false;
-        var keyCopy = new Key (Key);
-
-        //switch (KeyBindingScope)
-        //{
-        //    case KeyBindingScope.Application:
-        //        // Simulate a key down to invoke the Application scoped key binding
-        //        handled = Application.OnKeyDown (keyCopy);
+            case KeyBindingScope.Application:
+                break;
 
-        //        break;
-        //    case KeyBindingScope.Focused:
-        //        handled = InvokeCommand (Command.Value) == true;
-        //        handled = false;
+            case KeyBindingScope.Focused:
+                // TODO: Figure this out
+                handled = false;
 
-        //        break;
-        //    case KeyBindingScope.HotKey:
-        //        if (Command.HasValue)
-        //        {
-        //            //handled = _commandView.InvokeCommand (Gui.Command.HotKey) == true;
-        //            //handled = false;
-        //        }
+                break;
+            case KeyBindingScope.HotKey:
+                handled = _commandView.InvokeCommand (Command.HotKey) == true;
+                handled = false;
 
-        //        break;
-        //}
+                break;
+        }
 
-        //if (handled == false)
+        if (handled == false)
         {
             var args = new HandledEventArgs ();
             Accept?.Invoke (this, args);
@@ -641,25 +606,56 @@ public class Shortcut : View
         return true;
     }
 
+    #endregion Accept Handling
+
+    #region Focus
+
     /// <inheritdoc/>
-    public override bool OnEnter (View view)
+    public override ColorScheme ColorScheme
     {
-        // TODO: This is a hack. Need to refine this.
-        var cs = new ColorScheme (ColorScheme)
+        get
         {
-            Normal = ColorScheme.Focus,
-            HotNormal = ColorScheme.HotFocus
-        };
-
-        // _container.ColorScheme = cs;
+            if (base.ColorScheme == null)
+            {
+                return SuperView?.ColorScheme ?? base.ColorScheme;
+            }
 
-        cs = new (ColorScheme)
+            return base.ColorScheme;
+        }
+        set
         {
-            Normal = ColorScheme.HotFocus,
-            HotNormal = ColorScheme.Focus
-        };
+            base.ColorScheme = value;
+
+            if (CommandView.CanFocus)
+            {
+                CommandView.ColorScheme = SuperView?.ColorScheme ?? ColorScheme;
+            }
+
+            if (ColorScheme != null)
+            {
+                var cs = new ColorScheme (ColorScheme)
+                {
+                    Normal = ColorScheme.HotNormal,
+                    HotNormal = ColorScheme.Normal
+                };
+                KeyView.ColorScheme = cs;
+            }
+
+            Border.ColorScheme = SuperView?.ColorScheme ?? ColorScheme;
+        }
+    }
 
-        //KeyView.ColorScheme = cs;
+    /// <inheritdoc/>
+    public override bool OnEnter (View view)
+    {
+        if (SuperView is { })
+        {
+            ColorScheme = new (SuperView?.ColorScheme)
+            {
+                Normal = SuperView.ColorScheme.Focus,
+                HotNormal = SuperView.ColorScheme.HotFocus
+            };
+        }
 
         return base.OnEnter (view);
     }
@@ -667,24 +663,42 @@ public class Shortcut : View
     /// <inheritdoc/>
     public override bool OnLeave (View view)
     {
-        // TODO: This is a hack. Need to refine this.
-        var cs = new ColorScheme (ColorScheme)
+        ColorScheme = null;
+
+        return base.OnLeave (view);
+        if (SuperView is { })
         {
-            Normal = ColorScheme.Normal,
-            HotNormal = ColorScheme.HotNormal
-        };
+            ColorScheme = new (SuperView?.ColorScheme)
+            {
+                Normal = SuperView.ColorScheme.Normal,
+                HotNormal = SuperView.ColorScheme.HotNormal
+            };
+        }
 
-        //   _container.ColorScheme = cs;
+        return base.OnLeave (view);
+    }
 
-        cs = new (ColorScheme)
-        {
-            Normal = ColorScheme.HotNormal,
-            HotNormal = ColorScheme.Normal
-        };
+    #endregion Focus
 
-        //KeyView.ColorScheme = cs;
+    /// <inheritdoc />
+    protected override void Dispose (bool disposing)
+    {
+        if (disposing)
+        {
+            if (CommandView?.IsAdded == false)
+            {
+                CommandView.Dispose ();
+            }
+            if (HelpView?.IsAdded == false)
+            {
+                HelpView.Dispose ();
+            }
+            if (KeyView?.IsAdded == false)
+            {
+                KeyView.Dispose ();
+            }
+        }
+        base.Dispose (disposing);
 
-        return base.OnLeave (view);
     }
 }
-

+ 30 - 16
UICatalog/Scenarios/Shortcuts.cs

@@ -50,13 +50,13 @@ public class Shortcuts : Scenario
             KeyBindingScope = KeyBindingScope.Application,
             BorderStyle = LineStyle.Dotted
         };
-        shortcut1.Border.Thickness = new (1, 0, 1, 0);
+        shortcut1.Border.Thickness = new (1, 1, 1, 1);
         Application.Top.Add (shortcut1);
 
         var shortcut2 = new Shortcut
         {
             X = 20,
-            Y = Pos.Bottom (shortcut1),
+            Y = Pos.Bottom (shortcut1) - 1,
             Width = Dim.Width (shortcut1),
             Key = Key.F2,
             Text = "Width is ^",
@@ -78,7 +78,7 @@ public class Shortcuts : Scenario
         shortcut2.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)shortcut2.CommandView).SelectedItem < ((RadioGroup)shortcut2.CommandView).RadioLabels.Length - 1)
                                 {
                                     ((RadioGroup)shortcut2.CommandView).SelectedItem++;
                                 }
@@ -87,7 +87,7 @@ public class Shortcuts : Scenario
                                     ((RadioGroup)shortcut2.CommandView).SelectedItem = 0;
                                 }
                             };
-        shortcut2.Border.Thickness = new (1, 0, 1, 0);
+        shortcut2.Border.Thickness = new (1, 1, 1, 1);
         Application.Top.Add (shortcut2);
 
         var shortcut3 = new Shortcut
@@ -101,7 +101,8 @@ public class Shortcuts : Scenario
             KeyBindingScope = KeyBindingScope.HotKey,
             BorderStyle = LineStyle.Dotted
         };
-        shortcut3.Border.Thickness = new (1, 0, 1, 0);
+        shortcut3.CommandView.CanFocus = true;
+        shortcut3.Border.Thickness = new (1, 1, 1, 0);
 
         ((CheckBox)shortcut3.CommandView).Toggled += (s, e) =>
                                                      {
@@ -135,23 +136,24 @@ public class Shortcuts : Scenario
             Width = Dim.Width (shortcut3),
             CommandView = new Button
             {
-                Title = "_Button"
+                Title = "B_utton",
             },
             HelpText = "Width is Fill",
             Key = Key.K,
             KeyBindingScope = KeyBindingScope.HotKey,
             BorderStyle = LineStyle.Dotted
         };
-
+        Button button = (Button)shortcut4.CommandView;
         shortcut4.CommandView.Accept += Button_Clicked;
-        shortcut4.Border.Thickness = new (1, 0, 1, 0);
+        shortcut4.CommandView.CanFocus = true;
+        shortcut4.Border.Thickness = new (1, 0, 1,0);
 
         Application.Top.Add (shortcut4);
 
         var shortcut5 = new Shortcut
         {
             X = 20,
-            Y = Pos.Bottom (shortcut4),
+            Y = Pos.Bottom (shortcut4) ,
             Width = Dim.Width (shortcut4),
 
             Title = "Fi_ve",
@@ -160,14 +162,14 @@ public class Shortcuts : Scenario
             KeyBindingScope = KeyBindingScope.HotKey,
             BorderStyle = LineStyle.Dotted
         };
-        shortcut5.Border.Thickness = new (1, 0, 1, 0);
+        shortcut5.Border.Thickness = new (1, 0, 1, 1);
 
         Application.Top.Add (shortcut5);
 
         var shortcutSlider = new Shortcut
         {
             X = 20,
-            Y = Pos.Bottom (shortcut5),
+            Y = Pos.Bottom (shortcut5) - 1,
             Key = Key.F5,
             HelpText = "Width is Fill",
             Width = Dim.Width (shortcut5),
@@ -181,9 +183,9 @@ public class Shortcuts : Scenario
             }
         };
 
-        ((Slider<string>)shortcutSlider.CommandView).Options = new() { new () { Legend = "A" }, new () { Legend = "B" }, new () { Legend = "C" } };
+        ((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, 0, 1, 0);
+        shortcutSlider.Border.Thickness = new (1, 1, 1, 1);
 
         ((Slider<string>)shortcutSlider.CommandView).OptionsChanged += (o, args) =>
                                                                        {
@@ -193,20 +195,32 @@ public class Shortcuts : Scenario
 
         Application.Top.Add (shortcutSlider);
 
+        var shortcut6 = new Shortcut
+        {
+            X = 20,
+            Y = Pos.Bottom (shortcutSlider) - 1,
+            Width = Dim.Width (shortcutSlider),
+
+            Title = "_No Key",
+            HelpText = "Keyless",
+            BorderStyle = LineStyle.Dotted
+        };
+        shortcut6.Border.Thickness = new (1, 1, 1, 1);
+
+        Application.Top.Add (shortcut6);
+
         foreach (View sh in Application.Top.Subviews.Where (v => v is Shortcut)!)
         {
             if (sh is Shortcut shortcut)
             {
                 shortcut.Accept += (o, args) =>
                                    {
+                                       var x = button;
                                        eventSource.Add ($"Accept: {shortcut!.CommandView.Text}");
                                        eventLog.MoveDown ();
                                    };
             }
         }
-
-        //shortcut1.SetFocus ();
-        //View.Diagnostics = ViewDiagnosticFlags.Ruler;
     }
 
     private void Button_Clicked (object sender, EventArgs e) { MessageBox.Query ("Hi", $"You clicked {sender}"); }