Browse Source

Add AutoHideScrollBar and ShowScrollIndicator properties.

BDisp 11 months ago
parent
commit
6c972c67c3

+ 88 - 0
Terminal.Gui/Views/Scroll/ScrollBar.cs

@@ -35,6 +35,23 @@ public class ScrollBar : View
     private readonly ScrollButton _decrease;
     private readonly ScrollButton _decrease;
     private readonly ScrollButton _increase;
     private readonly ScrollButton _increase;
 
 
+    private bool _autoHideScrollBar = true;
+    private bool _showScrollIndicator = true;
+
+    /// <summary>If true the vertical/horizontal scroll bars won't be shown if it's not needed.</summary>
+    public bool AutoHideScrollBar
+    {
+        get => _autoHideScrollBar;
+        set
+        {
+            if (_autoHideScrollBar != value)
+            {
+                _autoHideScrollBar = value;
+                AdjustAll ();
+            }
+        }
+    }
+
     /// <summary>Defines if a scrollbar is vertical or horizontal.</summary>
     /// <summary>Defines if a scrollbar is vertical or horizontal.</summary>
     public Orientation Orientation
     public Orientation Orientation
     {
     {
@@ -67,6 +84,39 @@ public class ScrollBar : View
     /// </summary>
     /// </summary>
     public event EventHandler<CancelEventArgs<int>>? PositionChanging;
     public event EventHandler<CancelEventArgs<int>>? PositionChanging;
 
 
+    /// <summary>Gets or sets the visibility for the vertical or horizontal scroll indicator.</summary>
+    /// <value><c>true</c> if show vertical or horizontal scroll indicator; otherwise, <c>false</c>.</value>
+    public bool ShowScrollIndicator
+    {
+        get => Visible;
+        set
+        {
+            if (value == _showScrollIndicator)
+            {
+                return;
+            }
+
+            _showScrollIndicator = value;
+
+            if (IsInitialized)
+            {
+                SetNeedsLayout ();
+
+                if (value)
+                {
+                    Visible = true;
+                }
+                else
+                {
+                    Visible = false;
+                    Position = 0;
+                }
+
+                AdjustAll ();
+            }
+        }
+    }
+
     /// <summary>
     /// <summary>
     ///     Gets or sets the size of the Scroll. This is the total size of the content that can be scrolled through.
     ///     Gets or sets the size of the Scroll. This is the total size of the content that can be scrolled through.
     /// </summary>
     /// </summary>
@@ -95,11 +145,49 @@ public class ScrollBar : View
 
 
     private void AdjustAll ()
     private void AdjustAll ()
     {
     {
+        CheckScrollBarVisibility ();
         _scroll.AdjustScroll ();
         _scroll.AdjustScroll ();
         _decrease.AdjustButton ();
         _decrease.AdjustButton ();
         _increase.AdjustButton ();
         _increase.AdjustButton ();
     }
     }
 
 
+    private bool CheckScrollBarVisibility ()
+    {
+        if (!AutoHideScrollBar)
+        {
+            if (Visible != _showScrollIndicator)
+            {
+                Visible = _showScrollIndicator;
+                SetNeedsDisplay ();
+            }
+
+            return _showScrollIndicator;
+        }
+
+        int barSize = Orientation == Orientation.Vertical ? Viewport.Height : Viewport.Width;
+
+        if (barSize == 0 || barSize >= Size)
+        {
+            if (ShowScrollIndicator)
+            {
+                Visible = false;
+                SetNeedsDisplay ();
+
+                return false;
+            }
+        }
+        else
+        {
+            if (!Visible)
+            {
+                Visible = true;
+                SetNeedsDisplay ();
+            }
+        }
+
+        return true;
+    }
+
     private void Resize (Orientation orientation)
     private void Resize (Orientation orientation)
     {
     {
         switch (orientation)
         switch (orientation)

+ 9 - 1
UICatalog/Scenarios/ScrollBarDemo.cs

@@ -182,9 +182,17 @@ public class ScrollBarDemo : Scenario
                                             }
                                             }
                                         };
                                         };
 
 
+        var ckbAutoHideScrollBar = new CheckBox { Y = Pos.Bottom (scrollPosition), Text = "AutoHideScrollBar" };
+        ckbAutoHideScrollBar.CheckedStateChanging += (s, e) => scrollBar.AutoHideScrollBar = e.NewValue == CheckState.Checked;
+        view.Add (ckbAutoHideScrollBar);
+
+        var ckbShowScrollIndicator = new CheckBox { X = Pos.Right (ckbAutoHideScrollBar) + 1, Y = Pos.Bottom (scrollPosition), Text = "ShowScrollIndicator" };
+        ckbShowScrollIndicator.CheckedStateChanging += (s, e) => scrollBar.ShowScrollIndicator = e.NewValue == CheckState.Checked;
+        view.Add (ckbShowScrollIndicator);
+
         var lblSizeChanged = new Label
         var lblSizeChanged = new Label
         {
         {
-            Y = Pos.Bottom (lblPosition) + 1
+            Y = Pos.Bottom (ckbShowScrollIndicator) + 1
         };
         };
         view.Add (lblSizeChanged);
         view.Add (lblSizeChanged);
 
 

+ 130 - 48
UnitTests/Views/ScrollBarTests.cs

@@ -7,6 +7,42 @@ public class ScrollBarTests
     public ScrollBarTests (ITestOutputHelper output) { _output = output; }
     public ScrollBarTests (ITestOutputHelper output) { _output = output; }
     private readonly ITestOutputHelper _output;
     private readonly ITestOutputHelper _output;
 
 
+    [Fact]
+    [AutoInitShutdown]
+    public void AutoHideScrollBar_CheckScrollBarVisibility ()
+    {
+        var scrollBar = new ScrollBar { Width = 2, Height = Dim.Fill (), Size = 30 };
+        View scrollBarSuperView = ScrollBarSuperView ();
+        scrollBarSuperView.Add (scrollBar);
+        Application.Begin ((scrollBarSuperView.SuperView as Toplevel)!);
+
+        Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.Visible);
+        Assert.Equal ("Absolute(2)", scrollBar.Width!.ToString ());
+        Assert.Equal (2, scrollBar.Viewport.Width);
+        Assert.Equal ("Fill(Absolute(0))", scrollBar.Height!.ToString ());
+        Assert.Equal (25, scrollBar.Viewport.Height);
+
+        scrollBar.Size = 10;
+        Assert.False (scrollBar.ShowScrollIndicator);
+        Assert.False (scrollBar.Visible);
+
+        scrollBar.Size = 30;
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.Visible);
+
+        scrollBar.AutoHideScrollBar = false;
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.Visible);
+
+        scrollBar.Size = 10;
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.Visible);
+
+        scrollBarSuperView.SuperView!.Dispose ();
+    }
+
     [Theory]
     [Theory]
     [AutoInitShutdown]
     [AutoInitShutdown]
     [InlineData (
     [InlineData (
@@ -189,6 +225,10 @@ public class ScrollBarTests
         Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
         Assert.Equal (Orientation.Vertical, scrollBar.Orientation);
         Assert.Equal (0, scrollBar.Size);
         Assert.Equal (0, scrollBar.Size);
         Assert.Equal (0, scrollBar.Position);
         Assert.Equal (0, scrollBar.Position);
+        Assert.Equal ("Auto(Content,Absolute(1),)", scrollBar.Width!.ToString ());
+        Assert.Equal ("Auto(Content,Absolute(1),)", scrollBar.Height!.ToString ());
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.AutoHideScrollBar);
     }
     }
 
 
     [Theory]
     [Theory]
@@ -707,6 +747,65 @@ public class ScrollBarTests
         Assert.Null (Application.MouseGrabView);
         Assert.Null (Application.MouseGrabView);
     }
     }
 
 
+    [Theory]
+    [AutoInitShutdown]
+    [InlineData (Orientation.Vertical)]
+    [InlineData (Orientation.Horizontal)]
+    public void Mouse_Pressed_On_ScrollButton_Changes_Position (Orientation orientation)
+    {
+        var scrollBar = new ScrollBar
+        {
+            X = 10, Y = 10, Width = orientation == Orientation.Vertical ? 1 : 10, Height = orientation == Orientation.Vertical ? 10 : 1, Size = 20,
+            Orientation = orientation
+        };
+        var top = new Toplevel ();
+        top.Add (scrollBar);
+        Application.Begin (top);
+
+        var scroll = (Scroll)scrollBar.Subviews.FirstOrDefault (x => x is Scroll);
+        Rectangle scrollSliderFrame = scroll!.Subviews.FirstOrDefault (x => x is ScrollSlider)!.Frame;
+        Assert.Equal (scrollSliderFrame, orientation == Orientation.Vertical ? new (0, 0, 1, 4) : new (0, 0, 4, 1));
+        Assert.Equal (0, scrollBar.Position);
+
+        // ScrollButton increase
+        for (var i = 0; i < 13; i++)
+        {
+            Application.OnMouseEvent (
+                                      new ()
+                                      {
+                                          Position = orientation == Orientation.Vertical ? new (10, 19) : new (19, 10), Flags = MouseFlags.Button1Pressed
+                                      });
+
+            if (i < 12)
+            {
+                Assert.Equal (i + 1, scrollBar.Position);
+            }
+            else
+            {
+                Assert.Equal (i, scrollBar.Position);
+
+                Assert.Equal (
+                              orientation == Orientation.Vertical ? new (0, 4) : new (4, 0),
+                              scroll.Subviews.FirstOrDefault (x => x is ScrollSlider)!.Frame.Location);
+            }
+        }
+
+        for (var i = 12; i > -1; i--)
+        {
+            Application.OnMouseEvent (new () { Position = new (10, 10), Flags = MouseFlags.Button1Pressed });
+
+            if (i > 0)
+            {
+                Assert.Equal (i - 1, scrollBar.Position);
+            }
+            else
+            {
+                Assert.Equal (0, scrollBar.Position);
+                Assert.Equal (new (0, 0), scroll.Subviews.FirstOrDefault (x => x is ScrollSlider)!.Frame.Location);
+            }
+        }
+    }
+
     [Theory]
     [Theory]
     [AutoInitShutdown]
     [AutoInitShutdown]
     [InlineData (Orientation.Vertical)]
     [InlineData (Orientation.Vertical)]
@@ -877,6 +976,30 @@ public class ScrollBarTests
         }
         }
     }
     }
 
 
+    [Fact]
+    [AutoInitShutdown]
+    public void ShowScrollIndicator_CheckScrollBarVisibility ()
+    {
+        var scrollBar = new ScrollBar { Width = 2, Height = Dim.Fill (), Size = 30 };
+        View scrollBarSuperView = ScrollBarSuperView ();
+        scrollBarSuperView.Add (scrollBar);
+        Application.Begin ((scrollBarSuperView.SuperView as Toplevel)!);
+
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.Visible);
+
+        scrollBar.ShowScrollIndicator = false;
+        Assert.True (scrollBar.AutoHideScrollBar);
+        Assert.True (scrollBar.ShowScrollIndicator);
+        Assert.True (scrollBar.Visible);
+
+        scrollBar.AutoHideScrollBar = false;
+        Assert.False (scrollBar.ShowScrollIndicator);
+        Assert.False (scrollBar.Visible);
+
+        scrollBarSuperView.SuperView!.Dispose ();
+    }
+
     [Fact]
     [Fact]
     public void SizeChanged_Event ()
     public void SizeChanged_Event ()
     {
     {
@@ -967,58 +1090,17 @@ public class ScrollBarTests
         _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
         _ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
     }
     }
 
 
-    [Theory]
-    [AutoInitShutdown]
-    [InlineData (Orientation.Vertical)]
-    [InlineData (Orientation.Horizontal)]
-    public void Mouse_Pressed_On_ScrollButton_Changes_Position (Orientation orientation)
+    private View ScrollBarSuperView ()
     {
     {
-        var scrollBar = new ScrollBar
+        var view = new View
         {
         {
-            X = 10, Y = 10, Width = orientation == Orientation.Vertical ? 1 : 10, Height = orientation == Orientation.Vertical ? 10 : 1, Size = 20,
-            Orientation = orientation
+            Width = Dim.Fill (),
+            Height = Dim.Fill ()
         };
         };
-        var top = new Toplevel ();
-        top.Add (scrollBar);
-        Application.Begin (top);
-
-        var scroll = (Scroll)scrollBar.Subviews.FirstOrDefault (x => x is Scroll);
-        Rectangle scrollSliderFrame = scroll!.Subviews.FirstOrDefault (x => x is ScrollSlider)!.Frame;
-        Assert.Equal (scrollSliderFrame, orientation == Orientation.Vertical ? new (0, 0, 1, 4) : new (0, 0, 4, 1));
-        Assert.Equal (0, scrollBar.Position);
-
-        // ScrollButton increase
-        for (int i = 0; i < 13; i++)
-        {
-            Application.OnMouseEvent (new () { Position = orientation == Orientation.Vertical ? new (10, 19) : new (19, 10), Flags = MouseFlags.Button1Pressed });
-
-            if (i < 12)
-            {
-                Assert.Equal (i + 1, scrollBar.Position);
-            }
-            else
-            {
-                Assert.Equal (i, scrollBar.Position);
-                Assert.Equal (
-                              orientation == Orientation.Vertical ? new (0, 4) : new (4, 0),
-                              scroll.Subviews.FirstOrDefault (x => x is ScrollSlider)!.Frame.Location);
-            }
 
 
-        }
-
-        for (int i = 12; i > -1; i--)
-        {
-            Application.OnMouseEvent (new () { Position = new (10, 10), Flags = MouseFlags.Button1Pressed });
+        var top = new Toplevel ();
+        top.Add (view);
 
 
-            if (i > 0)
-            {
-                Assert.Equal (i - 1, scrollBar.Position);
-            }
-            else
-            {
-                Assert.Equal (0, scrollBar.Position);
-                Assert.Equal (new (0, 0), scroll.Subviews.FirstOrDefault (x => x is ScrollSlider)!.Frame.Location);
-            }
-        }
+        return view;
     }
     }
 }
 }