Bladeren bron

Refactored ViewportSettings - Now makes more sense and LixtView works as before

Tig 1 jaar geleden
bovenliggende
commit
7644f631f0

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

@@ -649,6 +649,7 @@ public partial class View
                         start = nextStart;
                         x = startOffsetX;
                         y = startOffsetY;
+
                         break;
                     }
 
@@ -664,7 +665,7 @@ public partial class View
             }
         }
 
-        return null;
+        return start;
     }
 
 #nullable restore

+ 36 - 22
Terminal.Gui/View/ViewContent.cs

@@ -3,10 +3,10 @@
 namespace Terminal.Gui;
 
 /// <summary>
-///     Settings for how scrolling the <see cref="View.Viewport"/> on the View's Content Area is handled.
+///     Settings for how the <see cref="View.Viewport"/> behaves relative to the View's Content area.
 /// </summary>
 [Flags]
-public enum ScrollSettings
+public enum ViewportSettings
 {
     /// <summary>
     ///     No settings.
@@ -22,7 +22,7 @@ public enum ScrollSettings
     ///     When not set, <see cref="View.Viewport"/> is constrained to the bounds of the Content Area rectangle in the horizontal direction.
     /// </para>
     /// </remarks>
-    AllowViewportOutsideContentHorizontal = 1,
+    AllowNegativeX = 1,
 
     /// <summary>
     ///     If set, <see cref="View.Viewport"/> can be set to a rectangle that does not perfectly intersect with the Content Area
@@ -33,7 +33,7 @@ public enum ScrollSettings
     ///     When not set, <see cref="View.Viewport"/> is constrained to the bounds of the Content Area rectangle in the vertical direction.
     /// </para>
     /// </remarks>
-    AllowViewportOutsideContentVertical = 2,
+    AllowNegativeY = 2,
 
     /// <summary>
     ///     If set, <see cref="View.Viewport"/> can be set to a rectangle that does not perfectly intersect with the Content Area
@@ -44,7 +44,13 @@ public enum ScrollSettings
     ///     When not set, <see cref="View.Viewport"/> is constrained to the bounds of the Content Area rectangle.
     /// </para>
     /// </remarks>
-    AllowViewportOutsideContent = AllowViewportOutsideContentHorizontal | AllowViewportOutsideContentVertical
+    AllowNegativeLocation = AllowNegativeX | AllowNegativeY,
+
+    AllowXGreaterThanContentWidth = 4,
+    AllowYGreaterThanContentHeight = 8,
+    AllowLocationCreaterThanContentSize = AllowXGreaterThanContentWidth | AllowYGreaterThanContentHeight,
+
+    ClearVisibleContentOnly = 16,
 }
 
 public partial class View
@@ -147,22 +153,22 @@ public partial class View
 
     #region Viewport
 
-    private ScrollSettings _scrollSettings;
+    private ViewportSettings _viewportSettings;
 
     /// <summary>
     ///     Gets or sets how scrolling the <see cref="View.Viewport"/> on the View's Content Area is handled.
     /// </summary>
-    public ScrollSettings ScrollSettings
+    public ViewportSettings ViewportSettings
     {
-        get => _scrollSettings;
+        get => _viewportSettings;
         set
         {
-            if (_scrollSettings == value)
+            if (_viewportSettings == value)
             {
                 return;
             }
 
-            _scrollSettings = value;
+            _viewportSettings = value;
 
             // Force set Viewport to cause settings to be applied as needed
             SetViewport (Viewport);
@@ -195,7 +201,7 @@ public partial class View
     ///         <see cref="ContentSize"/>. This enables virtual zoom.
     ///     </para>
     ///     <para>
-    ///         The <see cref="ScrollSettings"/> property controls how scrolling is handled. If <see cref="ScrollSettings"/> is
+    ///         The <see cref="ViewportSettings"/> property controls how scrolling is handled. If <see cref="ViewportSettings"/> is
     ///     </para>
     ///     <para>
     ///         If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value of Viewport is indeterminate until
@@ -274,33 +280,41 @@ public partial class View
         };
 
 
-        void ApplySettings (ref Rectangle location)
+        void ApplySettings (ref Rectangle newViewport)
         {
-            if (!ScrollSettings.HasFlag (ScrollSettings.AllowViewportOutsideContentHorizontal))
+            if (!ViewportSettings.HasFlag (ViewportSettings.AllowNegativeX))
             {
-                if (location.Y + Viewport.Height > ContentSize.Height)
+
+                if (newViewport.X < 0)
                 {
-                    location.Y = ContentSize.Height - Viewport.Height;
+                    newViewport.X = 0;
                 }
+            }
 
-                if (location.Y < 0)
+            if (!ViewportSettings.HasFlag (ViewportSettings.AllowXGreaterThanContentWidth))
+            {
+                if (newViewport.X >= ContentSize.Width)
                 {
-                    location.Y = 0;
+                    newViewport.X = ContentSize.Width - 1;
                 }
             }
 
-            if (!ScrollSettings.HasFlag (ScrollSettings.AllowViewportOutsideContentVertical))
+            if (!ViewportSettings.HasFlag (ViewportSettings.AllowNegativeY))
             {
-                if (location.X + Viewport.Width > ContentSize.Width)
+                if (newViewport.Y < 0)
                 {
-                    location.X = ContentSize.Width - Viewport.Width;
+                    newViewport.Y = 0;
                 }
+            }
 
-                if (location.X < 0)
+            if (!ViewportSettings.HasFlag (ViewportSettings.AllowYGreaterThanContentHeight))
+            {
+                if (newViewport.Y >= ContentSize.Height)
                 {
-                    location.X = 0;
+                    newViewport.Y = ContentSize.Height - 1;
                 }
             }
+
         }
     }
 

+ 8 - 8
Terminal.Gui/View/ViewDrawing.cs

@@ -99,13 +99,6 @@ public partial class View
 
         Rectangle toClear = new (-Viewport.Location.X, -Viewport.Location.Y, ContentSize.Width, ContentSize.Height);
 
-        // If toClear does not fill the Viewport, we need to clear the area outside toClear with DarkGray.
-        // TODO: Need a configurable color for this
-        // PERF: Put an if around this if toClear is not smaller than Viewport
-        Attribute prev = Driver.SetAttribute (new Attribute (ColorName.DarkGray, ColorName.DarkGray));
-        Rectangle viewport = new (Point.Empty, Viewport.Size);
-        Driver.FillRect (ViewportToScreen (viewport));
-        Driver.SetAttribute (prev);
 
         Clear (toClear);
     }
@@ -433,7 +426,14 @@ public partial class View
         {
             if (SuperView is { })
             {
-                ClearVisibleContent ();
+                if (ViewportSettings.HasFlag(ViewportSettings.ClearVisibleContentOnly))
+                {
+                    ClearVisibleContent ();
+                }
+                else
+                {
+                    Clear ();
+                }
             }
 
             if (!string.IsNullOrEmpty (TextFormatter.Text))

+ 13 - 50
Terminal.Gui/Views/ListView.cs

@@ -1,4 +1,5 @@
 using System.Collections;
+using static Terminal.Gui.SpinnerStyle;
 
 namespace Terminal.Gui;
 
@@ -106,13 +107,12 @@ public class ListView : View
     public ListView ()
     {
         CanFocus = true;
-        ScrollSettings = ScrollSettings.AllowViewportOutsideContent;
 
         // Things this view knows how to do
         AddCommand (Command.LineUp, () => MoveUp ());
         AddCommand (Command.LineDown, () => MoveDown ());
-        AddCommand (Command.ScrollUp, () => ScrollUp (1));
-        AddCommand (Command.ScrollDown, () => ScrollDown (1));
+        AddCommand (Command.ScrollUp, () => ScrollVertical (-1));
+        AddCommand (Command.ScrollDown, () => ScrollVertical (1));
         AddCommand (Command.PageUp, () => MovePageUp ());
         AddCommand (Command.PageDown, () => MovePageDown ());
         AddCommand (Command.TopHome, () => MoveHome ());
@@ -121,6 +121,9 @@ public class ListView : View
         AddCommand (Command.OpenSelectedItem, () => OnOpenSelectedItem ());
         AddCommand (Command.Select, () => MarkUnmarkRow ());
 
+        AddCommand (Command.ScrollLeft, () => ScrollHorizontal (-1));
+        AddCommand (Command.ScrollRight, () => ScrollHorizontal (1));
+
         // Default keybindings for all ListViews
         KeyBindings.Add (Key.CursorUp, Command.LineUp);
         KeyBindings.Add (Key.P.WithCtrl, Command.LineUp);
@@ -261,7 +264,7 @@ public class ListView : View
             }
             _source = value;
 
-            ContentSize = new Size (Viewport.Width, _source?.Count ?? 0);
+            ContentSize = new Size (_source?.Length ?? Viewport.Width, _source?.Count ?? Viewport.Width);
             Viewport = Viewport with { Y = 0 };
             KeystrokeNavigator.Collection = _source?.ToList ();
             _selected = -1;
@@ -383,28 +386,28 @@ public class ListView : View
 
         if (me.Flags == MouseFlags.WheeledDown)
         {
-            ScrollDown (1);
+            ScrollVertical (1);
 
             return true;
         }
 
         if (me.Flags == MouseFlags.WheeledUp)
         {
-            ScrollUp (1);
+            ScrollVertical (-1);
 
             return true;
         }
 
         if (me.Flags == MouseFlags.WheeledRight)
         {
-            ScrollRight (1);
+            ScrollHorizontal (1);
 
             return true;
         }
 
         if (me.Flags == MouseFlags.WheeledLeft)
         {
-            ScrollLeft (1);
+            ScrollHorizontal(-1);
 
             return true;
         }
@@ -792,46 +795,6 @@ public class ListView : View
     /// <summary>This event is invoked when this <see cref="ListView"/> is being drawn before rendering.</summary>
     public event EventHandler<ListViewRowEventArgs> RowRender;
 
-    /// <summary>Scrolls the view down by <paramref name="items"/> items.</summary>
-    /// <param name="items">Number of items to scroll down.</param>
-    public virtual bool ScrollDown (int items)
-    {
-        Viewport = Viewport with { Y = Math.Max (Math.Min (Viewport.Y + items, _source.Count - 1), 0) };
-        SetNeedsDisplay ();
-
-        return true;
-    }
-
-    /// <summary>Scrolls the view left.</summary>
-    /// <param name="cols">Number of columns to scroll left.</param>
-    public virtual bool ScrollLeft (int cols)
-    {
-        Viewport = Viewport with { X = Math.Max (Viewport.X - cols, 0) };
-        SetNeedsDisplay ();
-
-        return true;
-    }
-
-    /// <summary>Scrolls the view right.</summary>
-    /// <param name="cols">Number of columns to scroll right.</param>
-    public virtual bool ScrollRight (int cols)
-    {
-        Viewport = Viewport with { X = Math.Max (Math.Min (Viewport.X + cols, MaxLength - 1), 0) };
-        SetNeedsDisplay ();
-
-        return true;
-    }
-
-    /// <summary>Scrolls the view up by <paramref name="items"/> items.</summary>
-    /// <param name="items">Number of items to scroll up.</param>
-    public virtual bool ScrollUp (int items)
-    {
-        Viewport = Viewport with { Y = Math.Max (Viewport.Y - items, 0) };
-        SetNeedsDisplay ();
-
-        return true;
-    }
-
     /// <summary>This event is raised when the selected item in the <see cref="ListView"/> has changed.</summary>
     public event EventHandler<ListViewItemEventArgs> SelectedItemChanged;
 
@@ -1040,8 +1003,8 @@ public class ListWrapper : IListDataSource
 
     private void RenderUstr (ConsoleDriver driver, string ustr, int col, int line, int width, int start = 0)
     {
-        string u = TextFormatter.ClipAndJustify (ustr, width, TextAlignment.Left);
-        driver.AddStr (u);
+        string str = start > ustr.GetColumns () ? string.Empty : ustr.Substring (start);
+        string u = TextFormatter.ClipAndJustify (str, width, TextAlignment.Left); driver.AddStr (u);
         width -= u.GetColumns ();
 
         while (width-- > 0)

+ 67 - 20
UICatalog/Scenarios/VirtualContentScrolling.cs

@@ -25,7 +25,7 @@ public class VirtualScrolling : Scenario
 
             // TODO: Add a way to set the scroll settings in the Scenario
             ContentSize = new Size (60, 40);
-            ScrollSettings = ScrollSettings.AllowViewportOutsideContent;
+            ViewportSettings |= ViewportSettings.ClearVisibleContentOnly;
 
             // Things this view knows how to do
             AddCommand (Command.ScrollDown, () => ScrollVertical (1));
@@ -104,60 +104,107 @@ public class VirtualScrolling : Scenario
         var view = new VirtualDemoView { Title = "Virtual Scrolling" };
 
         // Add Scroll Setting UI to Padding
-        view.Padding.Thickness = new (0, 2, 0, 0);
+        view.Padding.Thickness = new (0, 3, 0, 0);
         view.Padding.ColorScheme = Colors.ColorSchemes["Error"];
 
-        var cbAllowXBeyondContent = new CheckBox ()
+        var cbAllowNegativeX = new CheckBox ()
         {
-            Title = "Allow Viewport._X Beyond Content",
+            Title = "Allow _X < 0",
             Y = 0,
             CanFocus = false
         };
-        cbAllowXBeyondContent.Checked = view.ScrollSettings.HasFlag (ScrollSettings.AllowViewportOutsideContentVertical);
-        cbAllowXBeyondContent.Toggled += NoRestrictHorizontal_Toggled;
+        cbAllowNegativeX.Checked = view.ViewportSettings.HasFlag (ViewportSettings.AllowNegativeX);
+        cbAllowNegativeX.Toggled += AllowNegativeX_Toggled;
 
-        void NoRestrictHorizontal_Toggled (object sender, StateEventArgs<bool?> e)
+        void AllowNegativeX_Toggled (object sender, StateEventArgs<bool?> e)
         {
             if (e.NewValue == true)
             {
-                view.ScrollSettings = view.ScrollSettings | ScrollSettings.AllowViewportOutsideContentVertical;
+                view.ViewportSettings |= ViewportSettings.AllowNegativeX;
             }
             else
             {
-                view.ScrollSettings = view.ScrollSettings & ~ScrollSettings.AllowViewportOutsideContentVertical;
+                view.ViewportSettings &= ~ViewportSettings.AllowNegativeX;
             }
         }
 
-        view.Padding.Add (cbAllowXBeyondContent);
+        view.Padding.Add (cbAllowNegativeX);
 
-        var cbAllowYBeyondContent = new CheckBox ()
+        var cbAllowNegativeY = new CheckBox ()
         {
-            Title = "Allow Viewport._Y Beyond Content",
-            X = Pos.Right (cbAllowXBeyondContent) + 1,
+            Title = "Allow _Y < 0",
+            X = Pos.Right (cbAllowNegativeX) + 1,
             Y = 0,
             CanFocus = false
         };
-        cbAllowYBeyondContent.Checked = view.ScrollSettings.HasFlag (ScrollSettings.AllowViewportOutsideContentHorizontal);
-        cbAllowYBeyondContent.Toggled += NoRestrictVertical_Toggled;
+        cbAllowNegativeY.Checked = view.ViewportSettings.HasFlag (ViewportSettings.AllowNegativeY);
+        cbAllowNegativeY.Toggled += AllowNegativeY_Toggled;
 
-        void NoRestrictVertical_Toggled (object sender, StateEventArgs<bool?> e)
+        void AllowNegativeY_Toggled (object sender, StateEventArgs<bool?> e)
         {
             if (e.NewValue == true)
             {
-                view.ScrollSettings = view.ScrollSettings | ScrollSettings.AllowViewportOutsideContentHorizontal;
+                view.ViewportSettings |= ViewportSettings.AllowNegativeY;
             }
             else
             {
-                view.ScrollSettings = view.ScrollSettings & ~ScrollSettings.AllowViewportOutsideContentHorizontal;
+                view.ViewportSettings &= ~ViewportSettings.AllowNegativeY;
             }
         }
 
-        view.Padding.Add (cbAllowYBeyondContent);
+        view.Padding.Add (cbAllowNegativeY);
+        
+        var cbAllowXGreaterThanContentWidth = new CheckBox ()
+        {
+            Title = "Allow X > Content",
+            Y = Pos.Bottom(cbAllowNegativeX),
+            CanFocus = false
+        };
+        cbAllowXGreaterThanContentWidth.Checked = view.ViewportSettings.HasFlag (ViewportSettings.AllowXGreaterThanContentWidth);
+        cbAllowXGreaterThanContentWidth.Toggled += AllowXGreaterThanContentWidth_Toggled;
+
+        void AllowXGreaterThanContentWidth_Toggled (object sender, StateEventArgs<bool?> e)
+        {
+            if (e.NewValue == true)
+            {
+                view.ViewportSettings |= ViewportSettings.AllowXGreaterThanContentWidth;
+            }
+            else
+            {
+                view.ViewportSettings &= ~ViewportSettings.AllowXGreaterThanContentWidth;
+            }
+        }
+
+        view.Padding.Add (cbAllowXGreaterThanContentWidth);
+
+        var cbAllowYGreaterThanContentHeight = new CheckBox ()
+        {
+            Title = "Allow Y > Content",
+            X = Pos.Right (cbAllowXGreaterThanContentWidth) + 1,
+            Y = Pos.Bottom (cbAllowNegativeX),
+            CanFocus = false
+        };
+        cbAllowYGreaterThanContentHeight.Checked = view.ViewportSettings.HasFlag (ViewportSettings.AllowYGreaterThanContentHeight);
+        cbAllowYGreaterThanContentHeight.Toggled += AllowYGreaterThanContentHeight_Toggled;
+
+        void AllowYGreaterThanContentHeight_Toggled (object sender, StateEventArgs<bool?> e)
+        {
+            if (e.NewValue == true)
+            {
+                view.ViewportSettings |= ViewportSettings.AllowYGreaterThanContentHeight;
+            }
+            else
+            {
+                view.ViewportSettings &= ~ViewportSettings.AllowYGreaterThanContentHeight;
+            }
+        }
+
+        view.Padding.Add (cbAllowYGreaterThanContentHeight);
 
         var labelContentSize = new Label ()
         {
             Title = "_ContentSize:",
-            Y = 1,
+            Y = Pos.Bottom(cbAllowYGreaterThanContentHeight),
         };
 
         var contentSizeWidth = new Buttons.NumericUpDown()

+ 1 - 1
UnitTests/View/Layout/ToScreenTests.cs

@@ -630,7 +630,7 @@ public class ToScreenTests (ITestOutputHelper output)
         {
             Width = 10,
             Height = 10,
-            ScrollSettings = ScrollSettings.AllowViewportOutsideContent
+            ViewportSettings = ViewportSettings.AllowNegativeLocation
         };
 
         Rectangle testRect = new Rectangle (0, 0, 1, 1);

+ 1 - 1
UnitTests/View/Layout/ViewportTests.cs

@@ -161,7 +161,7 @@ public class ViewportTests (ITestOutputHelper output)
         {
             Width = 10,
             Height = 10,
-            ScrollSettings = ScrollSettings.AllowViewportOutsideContent
+            ViewportSettings = ViewportSettings.AllowNegativeLocation
         };
 
         Assert.Equal (new Rectangle (0, 0, 10, 10), view.Frame);

+ 5 - 5
UnitTests/Views/ListViewTests.cs

@@ -78,7 +78,7 @@ public class ListViewTests
                                                       _output
                                                      );
 
-        Assert.True (lv.ScrollDown (10));
+        Assert.True (lv.ScrollVertical(10));
         lv.Draw ();
         Assert.Equal (-1, lv.SelectedItem);
 
@@ -141,7 +141,7 @@ public class ListViewTests
                                                       _output
                                                      );
 
-        Assert.True (lv.ScrollUp (20));
+        Assert.True (lv.ScrollVertical (-20));
         lv.Draw ();
         Assert.Equal (19, lv.SelectedItem);
 
@@ -183,7 +183,7 @@ public class ListViewTests
                                                       _output
                                                      );
 
-        Assert.True (lv.ScrollUp (20));
+        Assert.True (lv.ScrollVertical (-20));
         lv.Draw ();
         Assert.Equal (19, lv.SelectedItem);
 
@@ -246,7 +246,7 @@ public class ListViewTests
                                                       _output
                                                      );
 
-        Assert.True (lv.ScrollDown (20));
+        Assert.True (lv.ScrollVertical (20));
         lv.Draw ();
         Assert.Equal (0, lv.SelectedItem);
 
@@ -671,7 +671,7 @@ Item 6",
     private class NewListDataSource : IListDataSource
     {
         public int Count => 0;
-        public int Length => throw new NotImplementedException ();
+        public int Length => 0;
         public bool IsMarked (int item) { throw new NotImplementedException (); }
 
         public void Render (