diff --git a/Terminal.Gui/View/ViewDrawing.cs b/Terminal.Gui/View/ViewDrawing.cs index a0c6cc703..192ecf0d0 100644 --- a/Terminal.Gui/View/ViewDrawing.cs +++ b/Terminal.Gui/View/ViewDrawing.cs @@ -442,9 +442,6 @@ public partial class View // This should NOT clear // TODO: If the output is not in the Viewport, do nothing - if (Viewport.Y != 0) - { } - var drawRect = new Rectangle (ContentToScreen (Point.Empty), ContentSize); TextFormatter?.Draw ( diff --git a/Terminal.Gui/View/ViewScrolling.cs b/Terminal.Gui/View/ViewScrolling.cs index 2879d84f5..b07f968b0 100644 --- a/Terminal.Gui/View/ViewScrolling.cs +++ b/Terminal.Gui/View/ViewScrolling.cs @@ -44,9 +44,35 @@ public partial class View public Size ContentSize { get => _contentSize == Size.Empty ? Viewport.Size : _contentSize; - set => _contentSize = value; + set + { + _contentSize = value; + OnContentSizeChanged (new (_contentSize)); + } } + /// + /// Called when the changes. Invokes the event. + /// + /// + /// + protected bool? OnContentSizeChanged (SizeChangedEventArgs e) + { + ContentSizeChanged?.Invoke (this, e); + + if (e.Cancel != true) + { + SetNeedsDisplay (); + } + + return e.Cancel == true; + } + + /// + /// Event that is raised when the changes. + /// + public event EventHandler ContentSizeChanged; + /// /// Converts a content-relative location to a screen-relative location. /// diff --git a/Terminal.Gui/Views/ScrollBarView.cs b/Terminal.Gui/Views/ScrollBarView.cs index a85fdb21c..e56e4d2c5 100644 --- a/Terminal.Gui/Views/ScrollBarView.cs +++ b/Terminal.Gui/Views/ScrollBarView.cs @@ -275,7 +275,7 @@ public class ScrollBarView : View public event EventHandler ChangedPosition; /// - protected internal override bool OnMouseEvent (MouseEvent mouseEvent) + protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { if (mouseEvent.Flags != MouseFlags.Button1Pressed && mouseEvent.Flags != MouseFlags.Button1DoubleClicked @@ -524,8 +524,7 @@ public class ScrollBarView : View by1 = Math.Max (by1 - 1, 0); } - Move (col, 0); - Driver.AddRune (Glyphs.UpArrow); + AddRune (col, 0, Glyphs.UpArrow); var hasTopTee = false; var hasDiamond = false; @@ -533,7 +532,6 @@ public class ScrollBarView : View for (var y = 0; y < bh; y++) { - Move (col, y + 1); if ((y < by1 || y > by2) && ((_position > 0 && !hasTopTee) || (hasTopTee && hasBottomTee))) { @@ -567,17 +565,15 @@ public class ScrollBarView : View } } - Driver.AddRune (special); + AddRune (col, y + 1, special); } if (!hasTopTee) { - Move (col, Viewport.Height - 2); - Driver.AddRune (Glyphs.TopTee); + AddRune (col, Viewport.Height - 2, Glyphs.TopTee); } - Move (col, Viewport.Height - 1); - Driver.AddRune (Glyphs.DownArrow); + AddRune (col, Viewport.Height - 1, Glyphs.DownArrow); } } else diff --git a/Terminal.Gui/Views/ScrollView.cs b/Terminal.Gui/Views/ScrollView.cs index 22161404a..e35c8d874 100644 --- a/Terminal.Gui/Views/ScrollView.cs +++ b/Terminal.Gui/Views/ScrollView.cs @@ -33,7 +33,6 @@ public class ScrollView : View private bool _autoHideScrollBars = true; private View _contentBottomRightCorner; private Point _contentOffset; - private Size _contentSize; private bool _keepContentAlwaysInViewport = true; private bool _showHorizontalScrollIndicator; private bool _showVerticalScrollIndicator; @@ -89,10 +88,10 @@ public class ScrollView : View AddCommand (Command.PageDown, () => ScrollDown (Viewport.Height)); AddCommand (Command.PageLeft, () => ScrollLeft (Viewport.Width)); AddCommand (Command.PageRight, () => ScrollRight (Viewport.Width)); - AddCommand (Command.TopHome, () => ScrollUp (_contentSize.Height)); - AddCommand (Command.BottomEnd, () => ScrollDown (_contentSize.Height)); - AddCommand (Command.LeftHome, () => ScrollLeft (_contentSize.Width)); - AddCommand (Command.RightEnd, () => ScrollRight (_contentSize.Width)); + AddCommand (Command.TopHome, () => ScrollUp (ContentSize.Height)); + AddCommand (Command.BottomEnd, () => ScrollDown (ContentSize.Height)); + AddCommand (Command.LeftHome, () => ScrollLeft (ContentSize.Width)); + AddCommand (Command.RightEnd, () => ScrollRight (ContentSize.Width)); // Default keybindings for this view KeyBindings.Add (Key.CursorUp, Command.ScrollUp); @@ -134,6 +133,14 @@ public class ScrollView : View _vertical.ChangedPosition += delegate { ContentOffset = new Point (ContentOffset.X, _vertical.Position); }; _horizontal.ChangedPosition += delegate { ContentOffset = new Point (_horizontal.Position, ContentOffset.Y); }; }; + ContentSizeChanged += ScrollViewContentSizeChanged; + } + + private void ScrollViewContentSizeChanged (object sender, SizeChangedEventArgs e) + { + _contentView.Frame = new Rectangle (ContentOffset, e.Size with {Width = e.Size.Width-1, Height = e.Size.Height-1}); + _vertical.Size = e.Size.Height; + _horizontal.Size = e.Size.Width; } private void Application_UnGrabbedMouse (object sender, ViewEventArgs e) @@ -202,23 +209,23 @@ public class ScrollView : View } } - /// Represents the contents of the data shown inside the scrollview - /// The size of the content. - public new Size ContentSize - { - get => _contentSize; - set - { - if (_contentSize != value) - { - _contentSize = value; - _contentView.Frame = new Rectangle (_contentOffset, value); - _vertical.Size = _contentSize.Height; - _horizontal.Size = _contentSize.Width; - SetNeedsDisplay (); - } - } - } + ///// Represents the contents of the data shown inside the scrollview + ///// The size of the content. + //public new Size ContentSize + //{ + // get => ContentSize; + // set + // { + // if (ContentSize != value) + // { + // ContentSize = value; + // _contentView.Frame = new Rectangle (_contentOffset, value); + // _vertical.Size = ContentSize.Height; + // _horizontal.Size = ContentSize.Width; + // SetNeedsDisplay (); + // } + // } + //} /// Get or sets if the view-port is kept always visible in the area of this public bool KeepContentAlwaysInViewport @@ -233,26 +240,26 @@ public class ScrollView : View _horizontal.OtherScrollBarView.KeepContentAlwaysInViewport = value; Point p = default; - if (value && -_contentOffset.X + Viewport.Width > _contentSize.Width) + if (value && -_contentOffset.X + Viewport.Width > ContentSize.Width) { p = new Point ( - _contentSize.Width - Viewport.Width + (_showVerticalScrollIndicator ? 1 : 0), + ContentSize.Width - Viewport.Width + (_showVerticalScrollIndicator ? 1 : 0), -_contentOffset.Y ); } - if (value && -_contentOffset.Y + Viewport.Height > _contentSize.Height) + if (value && -_contentOffset.Y + Viewport.Height > ContentSize.Height) { if (p == default (Point)) { p = new Point ( -_contentOffset.X, - _contentSize.Height - Viewport.Height + (_showHorizontalScrollIndicator ? 1 : 0) + ContentSize.Height - Viewport.Height + (_showHorizontalScrollIndicator ? 1 : 0) ); } else { - p.Y = _contentSize.Height - Viewport.Height + (_showHorizontalScrollIndicator ? 1 : 0); + p.Y = ContentSize.Height - Viewport.Height + (_showHorizontalScrollIndicator ? 1 : 0); } } @@ -362,10 +369,8 @@ public class ScrollView : View { SetViewsNeedsDisplay (); - Rectangle savedClip = ClipToViewport (); - // TODO: It's bad practice for views to always clear a view. It negates clipping. - Clear (); + ClearVisibleContent(); if (!string.IsNullOrEmpty (_contentView.Text) || _contentView.Subviews.Count > 0) { @@ -373,8 +378,6 @@ public class ScrollView : View } DrawScrollBars (); - - Driver.Clip = savedClip; } /// @@ -606,7 +609,7 @@ public class ScrollView : View { // INTENT: Unclear intent. How about a call to Offset? _contentOffset = new Point (-Math.Abs (offset.X), -Math.Abs (offset.Y)); - _contentView.Frame = new Rectangle (_contentOffset, _contentSize); + _contentView.Frame = new Rectangle (_contentOffset, ContentSize); int p = Math.Max (0, -_contentOffset.Y); if (_vertical.Position != p) @@ -637,7 +640,7 @@ public class ScrollView : View bool v = false, h = false; var p = false; - if (Viewport.Height == 0 || Viewport.Height > _contentSize.Height) + if (Viewport.Height == 0 || Viewport.Height > ContentSize.Height) { if (ShowVerticalScrollIndicator) { @@ -646,7 +649,7 @@ public class ScrollView : View v = false; } - else if (Viewport.Height > 0 && Viewport.Height == _contentSize.Height) + else if (Viewport.Height > 0 && Viewport.Height == ContentSize.Height) { p = true; } @@ -660,7 +663,7 @@ public class ScrollView : View v = true; } - if (Viewport.Width == 0 || Viewport.Width > _contentSize.Width) + if (Viewport.Width == 0 || Viewport.Width > ContentSize.Width) { if (ShowHorizontalScrollIndicator) { @@ -669,7 +672,7 @@ public class ScrollView : View h = false; } - else if (Viewport.Width > 0 && Viewport.Width == _contentSize.Width && p) + else if (Viewport.Width > 0 && Viewport.Width == ContentSize.Width && p) { if (ShowHorizontalScrollIndicator) { @@ -721,13 +724,13 @@ public class ScrollView : View if (v) { - _vertical.SetRelativeLayout (ContentSize); + _vertical.SetRelativeLayout (Viewport.Size); _vertical.Draw (); } if (h) { - _horizontal.SetRelativeLayout (ContentSize); + _horizontal.SetRelativeLayout (Viewport.Size); _horizontal.Draw (); } @@ -735,7 +738,7 @@ public class ScrollView : View if (v && h) { - _contentBottomRightCorner.SetRelativeLayout (ContentSize); + _contentBottomRightCorner.SetRelativeLayout (Viewport.Size); _contentBottomRightCorner.Draw (); } } diff --git a/Terminal.Gui/Views/Toplevel.cs b/Terminal.Gui/Views/Toplevel.cs index b747dc048..47fdd9be7 100644 --- a/Terminal.Gui/Views/Toplevel.cs +++ b/Terminal.Gui/Views/Toplevel.cs @@ -287,7 +287,7 @@ public partial class Toplevel : View if (view.Frame.IntersectsWith (Viewport) && !OutsideTopFrame (this)) { //view.SetNeedsLayout (); - view.SetNeedsDisplay (view.Viewport); + view.SetNeedsDisplay (); view.SetSubViewNeedsDisplay (); } } diff --git a/UICatalog/Scenarios/VirtualContentScrolling.cs b/UICatalog/Scenarios/VirtualContentScrolling.cs index 096dcc6bb..e55ac36c6 100644 --- a/UICatalog/Scenarios/VirtualContentScrolling.cs +++ b/UICatalog/Scenarios/VirtualContentScrolling.cs @@ -100,7 +100,7 @@ public class VirtualScrolling : Scenario { Application.Init (); - var view = new VirtualDemoView { Title = "Virtual Demo View" }; + var view = new VirtualDemoView { Title = "Virtual Scrolling" }; var tf1 = new TextField { X = 20, Y = 7, Width = 10, Text = "TextField" }; var color = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (11) }; diff --git a/UnitTests/Views/ScrollViewTests.cs b/UnitTests/Views/ScrollViewTests.cs index a11be9d09..61fc5530e 100644 --- a/UnitTests/Views/ScrollViewTests.cs +++ b/UnitTests/Views/ScrollViewTests.cs @@ -354,7 +354,7 @@ public class ScrollViewTests Assert.True (sv.CanFocus); Assert.Equal (new Rectangle (1, 2, 20, 10), sv.Frame); Assert.Equal (Point.Empty, sv.ContentOffset); - Assert.Equal (Size.Empty, sv.ContentSize); + Assert.Equal (sv.Viewport.Size, sv.ContentSize); Assert.True (sv.AutoHideScrollBars); Assert.True (sv.KeepContentAlwaysInViewport); }