Fixed ScrollViwe

This commit is contained in:
Tig
2024-03-29 14:26:07 -06:00
parent 465c04f59f
commit 17efda9926
7 changed files with 78 additions and 56 deletions

View File

@@ -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 (

View File

@@ -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));
}
}
/// <summary>
/// Called when the <see cref="ContentSize"/> changes. Invokes the <see cref="ContentSizeChanged"/> event.
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
protected bool? OnContentSizeChanged (SizeChangedEventArgs e)
{
ContentSizeChanged?.Invoke (this, e);
if (e.Cancel != true)
{
SetNeedsDisplay ();
}
return e.Cancel == true;
}
/// <summary>
/// Event that is raised when the <see cref="ContentSize"/> changes.
/// </summary>
public event EventHandler<SizeChangedEventArgs> ContentSizeChanged;
/// <summary>
/// Converts a content-relative location to a screen-relative location.
/// </summary>

View File

@@ -275,7 +275,7 @@ public class ScrollBarView : View
public event EventHandler ChangedPosition;
/// <inheritdoc/>
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

View File

@@ -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
}
}
/// <summary>Represents the contents of the data shown inside the scrollview</summary>
/// <value>The size of the content.</value>
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 ();
}
}
}
///// <summary>Represents the contents of the data shown inside the scrollview</summary>
///// <value>The size of the content.</value>
//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 ();
// }
// }
//}
/// <summary>Get or sets if the view-port is kept always visible in the area of this <see cref="ScrollView"/></summary>
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;
}
/// <inheritdoc/>
@@ -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 ();
}
}

View File

@@ -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 ();
}
}

View File

@@ -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) };

View File

@@ -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);
}