Bläddra i källkod

Little things.

Tig 8 månader sedan
förälder
incheckning
06a636c2b7

+ 0 - 1
Terminal.Gui/View/View.Content.cs

@@ -218,7 +218,6 @@ public partial class View
             {
             {
                 // Force set Viewport to cause settings to be applied as needed
                 // Force set Viewport to cause settings to be applied as needed
                 SetViewport (Viewport);
                 SetViewport (Viewport);
-                SetScrollBarsKeepContentInAllViewport (_viewportSettings);
             }
             }
         }
         }
     }
     }

+ 59 - 98
Terminal.Gui/View/View.ScrollBars.cs

@@ -20,32 +20,12 @@ public partial class View
         _horizontalScrollBar = new (() => CreateScrollBar (Orientation.Horizontal));
         _horizontalScrollBar = new (() => CreateScrollBar (Orientation.Horizontal));
     }
     }
 
 
-    ///// <summary>
-    /////     Causes the scrollbar associated with <paramref name="orientation"/> to be explicitly created.
-    ///// </summary>
-    ///// <remarks>
-    /////     The built-in scrollbars are lazy-created internally. To enable them, the <see cref="VerticalScrollBar"/> or <see cref="HorizontalScrollBar"/>
-    /////     need to be referenced. All this method does is reference the associated property.
-    ///// </remarks>
-    ///// <param name="orientation"></param>
-    //public void EnableScrollBar (Orientation orientation)
-    //{
-    //    if (orientation == Orientation.Vertical)
-    //    {
-    //        _ = VerticalScrollBar; // Explicitly create the vertical scroll bar
-    //    }
-    //    else
-    //    {
-    //        _ = HorizontalScrollBar; // Explicitly create the horizontal scroll bar
-    //    }
-    //}
-
     private ScrollBar CreateScrollBar (Orientation orientation)
     private ScrollBar CreateScrollBar (Orientation orientation)
     {
     {
         var scrollBar = new ScrollBar
         var scrollBar = new ScrollBar
         {
         {
             Orientation = orientation,
             Orientation = orientation,
-            Visible = false, // Initially hidden until needed
+            Visible = false // Initially hidden until needed
         };
         };
 
 
         if (orientation == Orientation.Vertical)
         if (orientation == Orientation.Vertical)
@@ -59,62 +39,66 @@ public partial class View
 
 
         scrollBar.Initialized += OnScrollBarInitialized;
         scrollBar.Initialized += OnScrollBarInitialized;
 
 
+        // Add after setting Initialized event!
         Padding?.Add (scrollBar);
         Padding?.Add (scrollBar);
+
         return scrollBar;
         return scrollBar;
     }
     }
 
 
     private void ConfigureVerticalScrollBar (ScrollBar scrollBar)
     private void ConfigureVerticalScrollBar (ScrollBar scrollBar)
     {
     {
         scrollBar.X = Pos.AnchorEnd ();
         scrollBar.X = Pos.AnchorEnd ();
-        scrollBar.Height = Dim.Fill (Dim.Func (() =>
+
+        scrollBar.Height = Dim.Fill (
+                                     Dim.Func (
+                                               () =>
                                                {
                                                {
                                                    if (_horizontalScrollBar.IsValueCreated)
                                                    if (_horizontalScrollBar.IsValueCreated)
                                                    {
                                                    {
                                                        return _horizontalScrollBar.Value.Visible ? 1 : 0;
                                                        return _horizontalScrollBar.Value.Visible ? 1 : 0;
                                                    }
                                                    }
+
                                                    return 0;
                                                    return 0;
                                                }));
                                                }));
         scrollBar.ScrollableContentSize = GetContentSize ().Height;
         scrollBar.ScrollableContentSize = GetContentSize ().Height;
 
 
         ViewportChanged += (_, _) =>
         ViewportChanged += (_, _) =>
-        {
-            scrollBar.VisibleContentSize = Viewport.Height;
-            scrollBar.Position = Viewport.Y;
-        };
+                           {
+                               scrollBar.Position = Viewport.Y;
+                           };
 
 
-        ContentSizeChanged += (_, _) =>
-        {
-            scrollBar.ScrollableContentSize = GetContentSize ().Height;
-        };
+        ContentSizeChanged += (_, _) => { scrollBar.ScrollableContentSize = GetContentSize ().Height; };
     }
     }
 
 
     private void ConfigureHorizontalScrollBar (ScrollBar scrollBar)
     private void ConfigureHorizontalScrollBar (ScrollBar scrollBar)
     {
     {
         scrollBar.Y = Pos.AnchorEnd ();
         scrollBar.Y = Pos.AnchorEnd ();
-        scrollBar.Width = Dim.Fill (Dim.Func (() => {
+
+        scrollBar.Width = Dim.Fill (
+                                    Dim.Func (
+                                              () =>
+                                              {
                                                   if (_verticalScrollBar.IsValueCreated)
                                                   if (_verticalScrollBar.IsValueCreated)
                                                   {
                                                   {
                                                       return _verticalScrollBar.Value.Visible ? 1 : 0;
                                                       return _verticalScrollBar.Value.Visible ? 1 : 0;
                                                   }
                                                   }
+
                                                   return 0;
                                                   return 0;
                                               }));
                                               }));
         scrollBar.ScrollableContentSize = GetContentSize ().Width;
         scrollBar.ScrollableContentSize = GetContentSize ().Width;
 
 
         ViewportChanged += (_, _) =>
         ViewportChanged += (_, _) =>
-        {
-            scrollBar.VisibleContentSize = Viewport.Width;
-            scrollBar.Position = Viewport.X;
-        };
+                           {
+                               scrollBar.Position = Viewport.X;
+                           };
 
 
-        ContentSizeChanged += (_, _) =>
-        {
-            scrollBar.ScrollableContentSize = GetContentSize ().Width;
-        };
+        ContentSizeChanged += (_, _) => { scrollBar.ScrollableContentSize = GetContentSize ().Width; };
     }
     }
 
 
     private void OnScrollBarInitialized (object? sender, EventArgs e)
     private void OnScrollBarInitialized (object? sender, EventArgs e)
     {
     {
         var scrollBar = (ScrollBar)sender!;
         var scrollBar = (ScrollBar)sender!;
+
         if (scrollBar.Orientation == Orientation.Vertical)
         if (scrollBar.Orientation == Orientation.Vertical)
         {
         {
             ConfigureVerticalScrollBarEvents (scrollBar);
             ConfigureVerticalScrollBarEvents (scrollBar);
@@ -130,20 +114,20 @@ public partial class View
         Padding!.Thickness = Padding.Thickness with { Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : 0 };
         Padding!.Thickness = Padding.Thickness with { Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : 0 };
 
 
         scrollBar.PositionChanged += (_, args) =>
         scrollBar.PositionChanged += (_, args) =>
-        {
-            Viewport = Viewport with
-            {
-                Y = Math.Min (args.CurrentValue, GetContentSize ().Height - Viewport.Height)
-            };
-        };
+                                     {
+                                         Viewport = Viewport with
+                                         {
+                                             Y = Math.Min (args.CurrentValue, scrollBar.ScrollableContentSize - scrollBar.VisibleContentSize)
+                                         };
+                                     };
 
 
         scrollBar.VisibleChanged += (_, _) =>
         scrollBar.VisibleChanged += (_, _) =>
-        {
-            Padding.Thickness = Padding.Thickness with
-            {
-                Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : Padding.Thickness.Right - 1
-            };
-        };
+                                    {
+                                        Padding.Thickness = Padding.Thickness with
+                                        {
+                                            Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : Padding.Thickness.Right - 1
+                                        };
+                                    };
     }
     }
 
 
     private void ConfigureHorizontalScrollBarEvents (ScrollBar scrollBar)
     private void ConfigureHorizontalScrollBarEvents (ScrollBar scrollBar)
@@ -151,28 +135,40 @@ public partial class View
         Padding!.Thickness = Padding.Thickness with { Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : 0 };
         Padding!.Thickness = Padding.Thickness with { Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : 0 };
 
 
         scrollBar.PositionChanged += (_, args) =>
         scrollBar.PositionChanged += (_, args) =>
-        {
-            Viewport = Viewport with
-            {
-                X = Math.Min (args.CurrentValue, GetContentSize ().Width - Viewport.Width)
-            };
-        };
+                                     {
+                                         Viewport = Viewport with
+                                         {
+                                             X = Math.Min (args.CurrentValue, scrollBar.ScrollableContentSize - scrollBar.VisibleContentSize)
+                                         };
+                                     };
 
 
         scrollBar.VisibleChanged += (_, _) =>
         scrollBar.VisibleChanged += (_, _) =>
-        {
-            Padding.Thickness = Padding.Thickness with
-            {
-                Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : Padding.Thickness.Bottom - 1
-            };
-        };
+                                    {
+                                        Padding.Thickness = Padding.Thickness with
+                                        {
+                                            Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : Padding.Thickness.Bottom - 1
+                                        };
+                                    };
     }
     }
 
 
     /// <summary>
     /// <summary>
+    ///     Gets the horizontal <see cref="ScrollBar"/>. This property is lazy-loaded and will not be created until it is accessed.
     /// </summary>
     /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         See <see cref="ScrollBar"/> for more information on how to use the ScrollBar.
+    ///     </para>
+    /// </remarks>
     public ScrollBar HorizontalScrollBar => _horizontalScrollBar.Value;
     public ScrollBar HorizontalScrollBar => _horizontalScrollBar.Value;
 
 
     /// <summary>
     /// <summary>
+    ///     Gets the vertical <see cref="ScrollBar"/>. This property is lazy-loaded and will not be created until it is accessed.
     /// </summary>
     /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         See <see cref="ScrollBar"/> for more information on how to use the ScrollBar.
+    ///     </para>
+    /// </remarks>
     public ScrollBar VerticalScrollBar => _verticalScrollBar.Value;
     public ScrollBar VerticalScrollBar => _verticalScrollBar.Value;
 
 
     /// <summary>
     /// <summary>
@@ -197,39 +193,4 @@ public partial class View
             _verticalScrollBar.Value.Dispose ();
             _verticalScrollBar.Value.Dispose ();
         }
         }
     }
     }
-
-    private void SetScrollBarsKeepContentInAllViewport (ViewportSettings viewportSettings)
-    {
-        if (viewportSettings == ViewportSettings.None)
-        {
-            //_horizontalScrollBar.Value.KeepContentInAllViewport = true;
-            //_verticalScrollBar.Value.KeepContentInAllViewport = true;
-        }
-        else if (viewportSettings.HasFlag (ViewportSettings.AllowNegativeX))
-        {
-            _horizontalScrollBar.Value.AutoShow = false;
-        }
-        else if (viewportSettings.HasFlag (ViewportSettings.AllowNegativeY))
-        {
-            _verticalScrollBar.Value.AutoShow = false;
-        }
-        else if (viewportSettings.HasFlag (ViewportSettings.AllowNegativeLocation))
-        {
-            _horizontalScrollBar.Value.AutoShow = false;
-            _verticalScrollBar.Value.AutoShow = false;
-        }
-        else if (viewportSettings.HasFlag (ViewportSettings.AllowXGreaterThanContentWidth))
-        {
-            //_horizontalScrollBar.Value.KeepContentInAllViewport = false;
-        }
-        else if (viewportSettings.HasFlag (ViewportSettings.AllowYGreaterThanContentHeight))
-        {
-            //_verticalScrollBar.Value.KeepContentInAllViewport = false;
-        }
-        else if (viewportSettings.HasFlag (ViewportSettings.AllowLocationGreaterThanContentSize))
-        {
-            //_horizontalScrollBar.Value.KeepContentInAllViewport = false;
-            //_verticalScrollBar.Value.KeepContentInAllViewport = false;
-        }
-    }
 }
 }

+ 0 - 19
Terminal.Gui/View/ViewportSettings.cs

@@ -101,23 +101,4 @@ public enum ViewportSettings
     ///     disabled).
     ///     disabled).
     /// </summary>
     /// </summary>
     ClearContentOnly = 32,
     ClearContentOnly = 32,
-
-    /// <summary>
-    ///     If set, the vertical scroll bar (see <see cref="View.HorizontalScrollBar"/>) will be enabled and automatically made visible
-    ///     when the dimension of the <see cref="View.Viewport"/> is smaller than the dimension of <see cref="View.GetContentSize()"/>.
-    /// </summary>
-    EnableHorizontalScrollBar = 64,
-
-    /// <summary>
-    ///     If set, the vertical scroll bar (see <see cref="View.VerticalScrollBar"/>) will be enabled and automatically made visible
-    ///     when the dimension of the <see cref="View.Viewport"/> is smaller than the dimension of <see cref="View.GetContentSize()"/>.
-    /// </summary>
-    EnableVerticalScrollBar = 128,
-
-    /// <summary>
-    ///     If set, the horizontal and vertical scroll bars (see cref="View.HorizontalScrollBar"/> and <see cref="View.VerticalScrollBar"/>)
-    ///     will be enabled and automatically made visible when the dimension of the <see cref="View.Viewport"/> is smaller than the
-    ///     dimension of <see cref="View.GetContentSize()"/>.
-    /// </summary>
-    EnableScrollBars = EnableHorizontalScrollBar | EnableVerticalScrollBar
 }
 }

+ 10 - 7
Terminal.Gui/Views/ScrollBar/ScrollBar.cs

@@ -14,6 +14,9 @@ namespace Terminal.Gui;
 /// </summary>
 /// </summary>
 /// <remarks>
 /// <remarks>
 ///     <para>
 ///     <para>
+///         See the <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/scrolling.html">Scrolling Deep Dive</see>.
+///     </para>
+///     <para>
 ///         By default, the built-in View scrollbars have both <see cref="View.Visible"/> and <see cref="AutoShow"/> set to
 ///         By default, the built-in View scrollbars have both <see cref="View.Visible"/> and <see cref="AutoShow"/> set to
 ///         <see langword="false"/>.
 ///         <see langword="false"/>.
 ///         To enable them, either  set <see cref="AutoShow"/> set to <see langword="true"/> or explictly set
 ///         To enable them, either  set <see cref="AutoShow"/> set to <see langword="true"/> or explictly set
@@ -103,11 +106,11 @@ public class ScrollBar : View, IOrientation, IDesignable
 
 
         if (Orientation == Orientation.Vertical)
         if (Orientation == Orientation.Vertical)
         {
         {
-            _slider.VisibleContentSize = Viewport.Height;
+            _slider.VisibleContentSize = VisibleContentSize;
         }
         }
         else
         else
         {
         {
-            _slider.VisibleContentSize = Viewport.Width;
+            _slider.VisibleContentSize = VisibleContentSize;
         }
         }
 
 
         _slider.Size = CalculateSliderSize ();
         _slider.Size = CalculateSliderSize ();
@@ -194,7 +197,7 @@ public class ScrollBar : View, IOrientation, IDesignable
     #endregion
     #endregion
 
 
     /// <summary>
     /// <summary>
-    ///     Gets or sets the amount each mouse wheel event will incremenet/decrement the <see cref="Position"/>.
+    ///     Gets or sets the amount each mouse wheel event, or click on the increment/decrement buttons, will incremenet/decrement the <see cref="Position"/>.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     The default is 1.
     ///     The default is 1.
@@ -249,7 +252,7 @@ public class ScrollBar : View, IOrientation, IDesignable
     ///     <see cref="ScrollableContentSize"/>.
     ///     <see cref="ScrollableContentSize"/>.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
-    ///     If not explicitly set, will be the appropriate dimension of the Scroll's Frame.
+    ///     If not explicitly set, the visible content size will be appropriate dimension of the ScrollBar's Frame.
     /// </remarks>
     /// </remarks>
     public int VisibleContentSize
     public int VisibleContentSize
     {
     {
@@ -555,9 +558,9 @@ public class ScrollBar : View, IOrientation, IDesignable
         }
         }
 
 
 #if PROPORTIONAL_SCROLL_JUMP
 #if PROPORTIONAL_SCROLL_JUMP
-        // BUGBUG: This logic mostly works to provide a proportional jump. However, the math
-        // BUGBUG: falls apart in edge cases. Most other scroll bars (e.g. Windows) do not do proportional
-        // BUGBUG: Thus, this is disabled and we just jump a page each click.
+        // TODO: This logic mostly works to provide a proportional jump. However, the math
+        // TODO: falls apart in edge cases. Most other scroll bars (e.g. Windows) do not do proportional
+        // TODO: Thus, this is disabled; we just jump a page each click.
         // Ratio of the distance to the viewport dimension
         // Ratio of the distance to the viewport dimension
         double ratio = (double)Math.Abs (distanceFromCenter) / (VisibleContentSize);
         double ratio = (double)Math.Abs (distanceFromCenter) / (VisibleContentSize);
         // Jump size based on the ratio and the total content size
         // Jump size based on the ratio and the total content size

+ 55 - 89
UICatalog/Scenarios/CharacterMap/CharMap.cs

@@ -18,12 +18,13 @@ namespace UICatalog.Scenarios;
 public class CharMap : View, IDesignable
 public class CharMap : View, IDesignable
 {
 {
     private const int COLUMN_WIDTH = 3; // Width of each column of glyphs
     private const int COLUMN_WIDTH = 3; // Width of each column of glyphs
+    private const int HEADER_HEIGHT = 1; // Height of the header
     private int _rowHeight = 1; // Height of each row of 16 glyphs - changing this is not tested
     private int _rowHeight = 1; // Height of each row of 16 glyphs - changing this is not tested
 
 
     private ContextMenu _contextMenu = new ();
     private ContextMenu _contextMenu = new ();
 
 
     /// <summary>
     /// <summary>
-    ///     Initalizes a new instance.
+    ///     Initializes a new instance.
     /// </summary>
     /// </summary>
     public CharMap ()
     public CharMap ()
     {
     {
@@ -75,7 +76,7 @@ public class CharMap : View, IDesignable
                     Command.PageUp,
                     Command.PageUp,
                     () =>
                     () =>
                     {
                     {
-                        int page = (Viewport.Height - 1 / _rowHeight) * 16;
+                        int page = (Viewport.Height - HEADER_HEIGHT / _rowHeight) * 16;
                         SelectedCodePoint -= page;
                         SelectedCodePoint -= page;
 
 
                         return true;
                         return true;
@@ -86,7 +87,7 @@ public class CharMap : View, IDesignable
                     Command.PageDown,
                     Command.PageDown,
                     () =>
                     () =>
                     {
                     {
-                        int page = (Viewport.Height - 1 / _rowHeight) * 16;
+                        int page = (Viewport.Height - HEADER_HEIGHT / _rowHeight) * 16;
                         SelectedCodePoint += page;
                         SelectedCodePoint += page;
 
 
                         return true;
                         return true;
@@ -135,120 +136,92 @@ public class CharMap : View, IDesignable
         MouseClick += Handle_MouseClick;
         MouseClick += Handle_MouseClick;
         MouseEvent += Handle_MouseEvent;
         MouseEvent += Handle_MouseEvent;
 
 
-        // Add scrollbars
-        Padding!.Thickness = new (0, 0, 1, 0);
-
-        SetContentSize (new (COLUMN_WIDTH * 16 + RowLabelWidth, MAX_CODE_POINT / 16 * _rowHeight + 1)); // +1 for Header
+        SetContentSize (new (COLUMN_WIDTH * 16 + RowLabelWidth, MAX_CODE_POINT / 16 * _rowHeight + HEADER_HEIGHT));
 
 
+        // Set up the horizontal scrollbar. Turn off AutoShow since we do it manually.
         HorizontalScrollBar.AutoShow = false;
         HorizontalScrollBar.AutoShow = false;
         HorizontalScrollBar.Increment = COLUMN_WIDTH;
         HorizontalScrollBar.Increment = COLUMN_WIDTH;
+
+        // This prevents scrolling past the last column
         HorizontalScrollBar.ScrollableContentSize = GetContentSize ().Width - RowLabelWidth;
         HorizontalScrollBar.ScrollableContentSize = GetContentSize ().Width - RowLabelWidth;
         HorizontalScrollBar.X = RowLabelWidth;
         HorizontalScrollBar.X = RowLabelWidth;
         HorizontalScrollBar.Y = Pos.AnchorEnd ();
         HorizontalScrollBar.Y = Pos.AnchorEnd ();
         HorizontalScrollBar.Width = Dim.Fill (1);
         HorizontalScrollBar.Width = Dim.Fill (1);
 
 
-        VerticalScrollBar.AutoShow = false;
-        VerticalScrollBar.Visible = true;
-        VerticalScrollBar.ScrollableContentSize = GetContentSize ().Height;
-        VerticalScrollBar.X = Pos.AnchorEnd ();
-        VerticalScrollBar.Y = 1; // Header
-        VerticalScrollBar.Height = Dim.Fill (Dim.Func (() => Padding.Thickness.Bottom));
-
-        //VerticalScrollBar.PositionChanged += (sender, args) =>
-        //                                      {
-        //                                          if (Viewport.Height > 0)
-        //                                          {
-        //                                              Viewport = Viewport with
-        //                                              {
-        //                                                  Y = Math.Min (args.CurrentValue, GetContentSize ().Height - (Viewport.Height - 1))
-        //                                              };
-        //                                          }
-        //                                      };
-
-        //HorizontalScrollBar.PositionChanged += (sender, args) =>
-        //                                      {
-        //                                          if (Viewport.Width > 0)
-        //                                          {
-        //                                              Viewport = Viewport with
-        //                                              {
-        //                                                  X = Math.Min (args.CurrentValue, GetContentSize ().Width - Viewport.Width)
-        //                                              };
-        //                                          }
-        //                                      };
-
+        // We want the horizontal scrollbar to only show when needed.
+        // We can't use ScrollBar.AutoShow because we are using custom ContentSize
+        // So, we do it manually on ViewportChanged events.
         ViewportChanged += (sender, args) =>
         ViewportChanged += (sender, args) =>
-                        {
-                            if (Viewport.Width < GetContentSize ().Width)
-                            {
-                                HorizontalScrollBar.Visible = true;
-                            }
-                            else
-                            {
-                                HorizontalScrollBar.Visible = false;
-                            }
+                           {
+                               if (Viewport.Width < GetContentSize ().Width)
+                               {
+                                   HorizontalScrollBar.Visible = true;
+                               }
+                               else
+                               {
+                                   HorizontalScrollBar.Visible = false;
+                               }
+                           };
 
 
-                            VerticalScrollBar.VisibleContentSize = Viewport.Height - 1;
-                            HorizontalScrollBar.VisibleContentSize = Viewport.Width - RowLabelWidth;
-                        };
+        // Set up the vertical scrollbar. Turn off AutoShow since it's always visible.
+        VerticalScrollBar.AutoShow = false;
+        VerticalScrollBar.Visible = true; // Force always visible
+        VerticalScrollBar.X = Pos.AnchorEnd ();
+        VerticalScrollBar.Y = HEADER_HEIGHT; // Header
     }
     }
 
 
-    private void ScrollToMakeCursorVisible (Point newCursor)
+    private void ScrollToMakeCursorVisible (Point offsetToNewCursor)
     {
     {
         // Adjust vertical scrolling
         // Adjust vertical scrolling
-        if (newCursor.Y < 1) // Header is at Y = 0
+        if (offsetToNewCursor.Y < 1) // Header is at Y = 0
         {
         {
-            ScrollVertical (newCursor.Y - 1);
+            ScrollVertical (offsetToNewCursor.Y - HEADER_HEIGHT);
         }
         }
-        else if (newCursor.Y >= Viewport.Height)
+        else if (offsetToNewCursor.Y >= Viewport.Height)
         {
         {
-            ScrollVertical (newCursor.Y - Viewport.Height + 1);
+            ScrollVertical (offsetToNewCursor.Y - Viewport.Height + HEADER_HEIGHT);
         }
         }
 
 
         // Adjust horizontal scrolling
         // Adjust horizontal scrolling
-        if (newCursor.X < RowLabelWidth + 1)
+        if (offsetToNewCursor.X < RowLabelWidth + 1)
         {
         {
-            ScrollHorizontal (newCursor.X - (RowLabelWidth + 1));
+            ScrollHorizontal (offsetToNewCursor.X - (RowLabelWidth + 1));
         }
         }
-        else if (newCursor.X >= Viewport.Width)
+        else if (offsetToNewCursor.X >= Viewport.Width)
         {
         {
-            ScrollHorizontal (newCursor.X - Viewport.Width + 1);
+            ScrollHorizontal (offsetToNewCursor.X - Viewport.Width + 1);
         }
         }
-
-        //VerticalScrollBar.Position = Viewport.Y;
-        //HorizontalScrollBar.Position = Viewport.X;
     }
     }
 
 
     #region Cursor
     #region Cursor
 
 
-    /// <summary>Gets or sets the coordinates of the Cursor based on the SelectedCodePoint in Viewport-relative coordinates</summary>
-    public Point Cursor
+    private Point GetCursor (int codePoint)
     {
     {
-        get
-        {
-            int row = SelectedCodePoint / 16 * _rowHeight + 1 - Viewport.Y; // + 1 for header
-            int col = SelectedCodePoint % 16 * COLUMN_WIDTH + RowLabelWidth + 1 - Viewport.X; // + 1 for padding between label and first column
+        // + 1 for padding between label and first column
+        int x = codePoint % 16 * COLUMN_WIDTH + RowLabelWidth + 1 - Viewport.X;
+        int y = codePoint / 16 * _rowHeight + HEADER_HEIGHT - Viewport.Y;
 
 
-            return new (col, row);
-        }
-        set => throw new NotImplementedException ();
+        return new (x, y);
     }
     }
 
 
     public override Point? PositionCursor ()
     public override Point? PositionCursor ()
     {
     {
+        Point cursor = GetCursor (SelectedCodePoint);
+
         if (HasFocus
         if (HasFocus
-            && Cursor.X >= RowLabelWidth
-            && Cursor.X < Viewport.Width
-            && Cursor.Y > 0
-            && Cursor.Y < Viewport.Height)
+            && cursor.X >= RowLabelWidth
+            && cursor.X < Viewport.Width
+            && cursor.Y > 0
+            && cursor.Y < Viewport.Height)
         {
         {
-            Move (Cursor.X, Cursor.Y);
+            Move (cursor.X, cursor.Y);
         }
         }
         else
         else
         {
         {
             return null;
             return null;
         }
         }
 
 
-        return Cursor;
+        return cursor;
     }
     }
 
 
     #endregion Cursor
     #endregion Cursor
@@ -274,16 +247,12 @@ public class CharMap : View, IDesignable
 
 
             int newSelectedCodePoint = Math.Clamp (value, 0, MAX_CODE_POINT);
             int newSelectedCodePoint = Math.Clamp (value, 0, MAX_CODE_POINT);
 
 
-            Point newCursor = new ()
-            {
-                X = newSelectedCodePoint % 16 * COLUMN_WIDTH + RowLabelWidth + 1 - Viewport.X,
-                Y = newSelectedCodePoint / 16 * _rowHeight + 1 - Viewport.Y
-            };
+            Point offsetToNewCursor = GetCursor (newSelectedCodePoint);
 
 
             _selectedCodepoint = newSelectedCodePoint;
             _selectedCodepoint = newSelectedCodePoint;
 
 
             // Ensure the new cursor position is visible
             // Ensure the new cursor position is visible
-            ScrollToMakeCursorVisible (newCursor);
+            ScrollToMakeCursorVisible (offsetToNewCursor);
 
 
             SetNeedsDraw ();
             SetNeedsDraw ();
             SelectedCodePointChanged?.Invoke (this, new (SelectedCodePoint));
             SelectedCodePointChanged?.Invoke (this, new (SelectedCodePoint));
@@ -336,8 +305,8 @@ public class CharMap : View, IDesignable
             return true;
             return true;
         }
         }
 
 
-        int cursorCol = Cursor.X + Viewport.X - RowLabelWidth - 1;
-        int cursorRow = Cursor.Y + Viewport.Y - 1;
+        int cursorCol = GetCursor (SelectedCodePoint).X + Viewport.X - RowLabelWidth - 1;
+        int cursorRow = GetCursor (SelectedCodePoint).Y + Viewport.Y - 1;
 
 
         SetAttribute (GetHotNormalColor ());
         SetAttribute (GetHotNormalColor ());
         Move (0, 0);
         Move (0, 0);
@@ -504,7 +473,6 @@ public class CharMap : View, IDesignable
         if (e.Flags == MouseFlags.WheeledDown)
         if (e.Flags == MouseFlags.WheeledDown)
         {
         {
             ScrollVertical (1);
             ScrollVertical (1);
-//            _vScrollBar.Position = Viewport.Y;
             e.Handled = true;
             e.Handled = true;
 
 
             return;
             return;
@@ -513,7 +481,6 @@ public class CharMap : View, IDesignable
         if (e.Flags == MouseFlags.WheeledUp)
         if (e.Flags == MouseFlags.WheeledUp)
         {
         {
             ScrollVertical (-1);
             ScrollVertical (-1);
-  //          _vScrollBar.Position = Viewport.Y;
             e.Handled = true;
             e.Handled = true;
 
 
             return;
             return;
@@ -522,7 +489,6 @@ public class CharMap : View, IDesignable
         if (e.Flags == MouseFlags.WheeledRight)
         if (e.Flags == MouseFlags.WheeledRight)
         {
         {
             ScrollHorizontal (1);
             ScrollHorizontal (1);
-           // _hScrollBar.Position = Viewport.X;
             e.Handled = true;
             e.Handled = true;
 
 
             return;
             return;
@@ -531,7 +497,6 @@ public class CharMap : View, IDesignable
         if (e.Flags == MouseFlags.WheeledLeft)
         if (e.Flags == MouseFlags.WheeledLeft)
         {
         {
             ScrollHorizontal (-1);
             ScrollHorizontal (-1);
-       //     _hScrollBar.Position = Viewport.X;
             e.Handled = true;
             e.Handled = true;
         }
         }
     }
     }
@@ -545,12 +510,12 @@ public class CharMap : View, IDesignable
 
 
         if (me.Position.Y == 0)
         if (me.Position.Y == 0)
         {
         {
-            me.Position = me.Position with { Y = Cursor.Y };
+            me.Position = me.Position with { Y = GetCursor (SelectedCodePoint).Y };
         }
         }
 
 
         if (me.Position.X < RowLabelWidth || me.Position.X > RowLabelWidth + 16 * COLUMN_WIDTH - 1)
         if (me.Position.X < RowLabelWidth || me.Position.X > RowLabelWidth + 16 * COLUMN_WIDTH - 1)
         {
         {
-            me.Position = me.Position with { X = Cursor.X };
+            me.Position = me.Position with { X = GetCursor (SelectedCodePoint).X };
         }
         }
 
 
         int row = (me.Position.Y - 1 - -Viewport.Y) / _rowHeight; // -1 for header
         int row = (me.Position.Y - 1 - -Viewport.Y) / _rowHeight; // -1 for header
@@ -659,6 +624,7 @@ public class CharMap : View, IDesignable
             Height = Dim.Fill (3),
             Height = Dim.Fill (3),
             TextAlignment = Alignment.Center
             TextAlignment = Alignment.Center
         };
         };
+
         var spinner = new SpinnerView
         var spinner = new SpinnerView
         {
         {
             X = Pos.Center (),
             X = Pos.Center (),

+ 56 - 72
UICatalog/Scenarios/Scrolling.cs

@@ -15,7 +15,7 @@ public class Scrolling : Scenario
 
 
         var app = new Window
         var app = new Window
         {
         {
-            Title = GetQuitKeyAndName (),
+            Title = GetQuitKeyAndName ()
         };
         };
 
 
         var label = new Label { X = 0, Y = 0 };
         var label = new Label { X = 0, Y = 0 };
@@ -27,7 +27,7 @@ public class Scrolling : Scenario
             X = 2,
             X = 2,
             Y = Pos.Bottom (label) + 1,
             Y = Pos.Bottom (label) + 1,
             Width = 60,
             Width = 60,
-            Height = 20,
+            Height = 20
         };
         };
         demoView.SetContentSize (new (80, 25));
         demoView.SetContentSize (new (80, 25));
 
 
@@ -35,10 +35,10 @@ public class Scrolling : Scenario
             $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}";
             $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}";
 
 
         demoView.ViewportChanged += (_, _) =>
         demoView.ViewportChanged += (_, _) =>
-                                      {
-                                          label.Text =
-                                              $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}";
-                                      };
+                                    {
+                                        label.Text =
+                                            $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}";
+                                    };
 
 
         app.Add (demoView);
         app.Add (demoView);
 
 
@@ -54,10 +54,7 @@ public class Scrolling : Scenario
             CheckedState = demoView.HorizontalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
             CheckedState = demoView.HorizontalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
         };
         };
         app.Add (hCheckBox);
         app.Add (hCheckBox);
-        hCheckBox.CheckedStateChanged += (sender, args) =>
-                                         {
-                                             demoView.HorizontalScrollBar.Visible = args.CurrentValue == CheckState.Checked;
-                                         };
+        hCheckBox.CheckedStateChanged += (sender, args) => { demoView.HorizontalScrollBar.Visible = args.CurrentValue == CheckState.Checked; };
 
 
         //// NOTE: This call to EnableScrollBar is technically not needed because the reference
         //// NOTE: This call to EnableScrollBar is technically not needed because the reference
         //// NOTE: to demoView.HorizontalScrollBar below will cause it to be lazy created.
         //// NOTE: to demoView.HorizontalScrollBar below will cause it to be lazy created.
@@ -71,35 +68,29 @@ public class Scrolling : Scenario
             CheckedState = demoView.VerticalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
             CheckedState = demoView.VerticalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked
         };
         };
         app.Add (vCheckBox);
         app.Add (vCheckBox);
-        vCheckBox.CheckedStateChanged += (sender, args) =>
-                                         {
-                                             demoView.VerticalScrollBar.Visible = args.CurrentValue == CheckState.Checked;
-                                         };
+        vCheckBox.CheckedStateChanged += (sender, args) => { demoView.VerticalScrollBar.Visible = args.CurrentValue == CheckState.Checked; };
 
 
         var ahCheckBox = new CheckBox
         var ahCheckBox = new CheckBox
         {
         {
             X = Pos.Left (demoView),
             X = Pos.Left (demoView),
             Y = Pos.Bottom (hCheckBox),
             Y = Pos.Bottom (hCheckBox),
-            Text = "_AutoHide (both)",
+            Text = "_AutoShow (both)",
             CheckedState = demoView.HorizontalScrollBar.AutoShow ? CheckState.Checked : CheckState.UnChecked
             CheckedState = demoView.HorizontalScrollBar.AutoShow ? CheckState.Checked : CheckState.UnChecked
         };
         };
 
 
         ahCheckBox.CheckedStateChanging += (s, e) =>
         ahCheckBox.CheckedStateChanging += (s, e) =>
-                              {
-                                  demoView.HorizontalScrollBar.AutoShow = e.NewValue == CheckState.Checked;
-                                  demoView.VerticalScrollBar.AutoShow = e.NewValue == CheckState.Checked;
-                              };
+                                           {
+                                               demoView.HorizontalScrollBar.AutoShow = e.NewValue == CheckState.Checked;
+                                               demoView.VerticalScrollBar.AutoShow = e.NewValue == CheckState.Checked;
+                                           };
         app.Add (ahCheckBox);
         app.Add (ahCheckBox);
 
 
-        demoView.VerticalScrollBar.VisibleChanging += (sender, args) =>
-                                                     {
-                                                         vCheckBox.CheckedState = args.NewValue ? CheckState.Checked : CheckState.UnChecked; 
-                                                     };
+        demoView.VerticalScrollBar.VisibleChanging += (sender, args) => { vCheckBox.CheckedState = args.NewValue ? CheckState.Checked : CheckState.UnChecked; };
 
 
         demoView.HorizontalScrollBar.VisibleChanging += (sender, args) =>
         demoView.HorizontalScrollBar.VisibleChanging += (sender, args) =>
-                                                      {
-                                                          hCheckBox.CheckedState = args.NewValue ? CheckState.Checked : CheckState.UnChecked;
-                                                      };
+                                                        {
+                                                            hCheckBox.CheckedState = args.NewValue ? CheckState.Checked : CheckState.UnChecked;
+                                                        };
 
 
         var count = 0;
         var count = 0;
 
 
@@ -130,19 +121,16 @@ public class Scrolling : Scenario
 
 
         Application.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
         Application.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
 
 
-        app.Unloaded += app_Unloaded;
+        app.Unloaded += AppUnloaded;
 
 
         Application.Run (app);
         Application.Run (app);
-        app.Unloaded -= app_Unloaded;
+        app.Unloaded -= AppUnloaded;
         app.Dispose ();
         app.Dispose ();
         Application.Shutdown ();
         Application.Shutdown ();
 
 
         return;
         return;
 
 
-        void app_Unloaded (object sender, EventArgs args)
-        {
-            pulsing = false;
-        }
+        void AppUnloaded (object sender, EventArgs args) { pulsing = false; }
     }
     }
 }
 }
 
 
@@ -154,18 +142,17 @@ public class DemoView : View
         CanFocus = true;
         CanFocus = true;
         BorderStyle = LineStyle.Heavy;
         BorderStyle = LineStyle.Heavy;
         Arrangement = ViewArrangement.Resizable;
         Arrangement = ViewArrangement.Resizable;
-
         Initialized += OnInitialized;
         Initialized += OnInitialized;
-
-
+        HorizontalScrollBar.AutoShow = true;
+        VerticalScrollBar.AutoShow = true;
     }
     }
 
 
     private void OnInitialized (object sender, EventArgs e)
     private void OnInitialized (object sender, EventArgs e)
     {
     {
-        View rulerView = new View ()
+        var rulerView = new View
         {
         {
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Width = Dim.Fill (),
+            Width = Dim.Fill ()
         };
         };
         rulerView.Border!.Thickness = new (1);
         rulerView.Border!.Thickness = new (1);
         rulerView.Border.LineStyle = LineStyle.None;
         rulerView.Border.LineStyle = LineStyle.None;
@@ -174,7 +161,6 @@ public class DemoView : View
 
 
         Add (rulerView);
         Add (rulerView);
 
 
-
         var pressMeButton = new Button
         var pressMeButton = new Button
         {
         {
             X = 1,
             X = 1,
@@ -195,37 +181,37 @@ public class DemoView : View
         Add (aLongButton);
         Add (aLongButton);
 
 
         Add (
         Add (
-                        new TextField
-                        {
-                            X = Pos.Left (pressMeButton),
-                            Y = Pos.Bottom (aLongButton) + 1,
-                            Width = 50,
-                            ColorScheme = Colors.ColorSchemes ["Dialog"],
-                            Text = "This is a test of..."
-                        }
-                       );
+             new TextField
+             {
+                 X = Pos.Left (pressMeButton),
+                 Y = Pos.Bottom (aLongButton) + 1,
+                 Width = 50,
+                 ColorScheme = Colors.ColorSchemes ["Dialog"],
+                 Text = "This is a test of..."
+             }
+            );
 
 
         Add (
         Add (
-                        new TextField
-                        {
-                            X = Pos.Left (pressMeButton),
-                            Y = Pos.Bottom (aLongButton) + 3,
-                            Width = 50,
-                            ColorScheme = Colors.ColorSchemes ["Dialog"],
-                            Text = "... the emergency broadcast system."
-                        }
-                       );
+             new TextField
+             {
+                 X = Pos.Left (pressMeButton),
+                 Y = Pos.Bottom (aLongButton) + 3,
+                 Width = 50,
+                 ColorScheme = Colors.ColorSchemes ["Dialog"],
+                 Text = "... the emergency broadcast system."
+             }
+            );
 
 
         Add (
         Add (
-                        new TextField
-                        {
-                            X = Pos.Left (pressMeButton),
-                            Y = 40,
-                            Width = 50,
-                            ColorScheme = Colors.ColorSchemes ["Error"],
-                            Text = "Last line"
-                        }
-                       );
+             new TextField
+             {
+                 X = Pos.Left (pressMeButton),
+                 Y = 40,
+                 Width = 50,
+                 ColorScheme = Colors.ColorSchemes ["Error"],
+                 Text = "Last line"
+             }
+            );
 
 
         // Demonstrate AnchorEnd - Button is anchored to bottom/right
         // Demonstrate AnchorEnd - Button is anchored to bottom/right
         var anchorButton = new Button
         var anchorButton = new Button
@@ -236,13 +222,11 @@ public class DemoView : View
         };
         };
 
 
         anchorButton.Accepting += (s, e) =>
         anchorButton.Accepting += (s, e) =>
-        {
-            // This demonstrates how to have a dynamically sized button
-            // Each time the button is clicked the button's text gets longer
-            anchorButton.Text += "!";
-
-        };
+                                  {
+                                      // This demonstrates how to have a dynamically sized button
+                                      // Each time the button is clicked the button's text gets longer
+                                      anchorButton.Text += "!";
+                                  };
         Add (anchorButton);
         Add (anchorButton);
-
     }
     }
 }
 }