ScrollView

This commit is contained in:
Miguel de Icaza
2018-01-26 23:01:53 -05:00
parent 29d355660e
commit 3f2c6b6f97
2 changed files with 195 additions and 65 deletions

View File

@@ -1,7 +1,167 @@
using System; //
// ScrollView.cs: ScrollView and ScrollBarView views.
//
// Authors:
// Miguel de Icaza (miguel@gnome.org)
//
//
// TODO:
// - Mouse handling in scrollbarview
// - focus in scrollview
// - keyboard handling in scrollview to scroll
// - focus handling in scrollview to auto scroll to focused view
// - Raise events
using System;
namespace Terminal.Gui { namespace Terminal.Gui {
/// <summary> /// <summary>
/// /// ScrollBarViews are views that display a 1-character scrollbar, either horizontal or vertical
/// </summary>
/// <remarks>
/// The scrollbar is drawn to be a representation of the Size, assuming that the
/// scroll position is set at Position.
/// </remarks>
public class ScrollBarView : View {
bool vertical;
int size, position;
/// <summary>
/// The size that this scrollbar represents
/// </summary>
/// <value>The size.</value>
public int Size {
get => size;
set {
size = value;
SetNeedsDisplay ();
}
}
/// <summary>
/// The position to show the scrollbar at.
/// </summary>
/// <value>The position.</value>
public int Position {
get => position;
set {
position = value;
SetNeedsDisplay ();
}
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Terminal.Gui.ScrollBarView"/> class.
/// </summary>
/// <param name="rect">Frame for the scrollbar.</param>
/// <param name="size">The size that this scrollbar represents.</param>
/// <param name="position">The position within this scrollbar.</param>
/// <param name="isVertical">If set to <c>true</c> this is a vertical scrollbar, otherwize, the scrollbar is horizontal.</param>
public ScrollBarView (Rect rect, int size, int position, bool isVertical) : base (rect)
{
vertical = isVertical;
this.position = position;
this.size = size;
}
/// <summary>
/// Redraw the scrollbar
/// </summary>
/// <param name="region">Region to be redrawn.</param>
public override void Redraw(Rect region)
{
Driver.SetAttribute (ColorScheme.Normal);
if (vertical) {
if (region.Right < Bounds.Width - 1)
return;
var col = Bounds.Width - 1;
var bh = Bounds.Height;
SpecialChar special;
if (bh < 3) {
var by1 = position * bh / Size;
var by2 = (position + bh) * bh / Size;
for (int y = 0; y < bh; y++) {
Move (col, y);
if (y < by1 || y > by2)
special = SpecialChar.Stipple;
else
special = SpecialChar.Diamond;
Driver.AddSpecial (special);
}
} else {
bh -= 2;
var by1 = position * bh / Size;
var by2 = (position + bh) * bh / Size;
Move (col, 0);
Driver.AddRune ('^');
Move (col, Bounds.Height - 1);
Driver.AddRune ('v');
for (int y = 0; y < bh; y++) {
Move (col, y+1);
if (y < by1 || y > by2)
special = SpecialChar.Stipple;
else {
if (by2 - by1 == 0)
special = SpecialChar.Diamond;
else {
if (y == by1)
special = SpecialChar.TopTee;
else if (y == by2)
special = SpecialChar.BottomTee;
else
special = SpecialChar.VLine;
}
}
Driver.AddSpecial (special);
}
}
} else {
if (region.Bottom < Bounds.Height - 1)
return;
var row = Bounds.Height - 1;
var bw = Bounds.Width;
if (bw < 3) {
} else {
bw -= 2;
var bx1 = position * bw / Size;
var bx2 = (position + bw) * bw / Size;
Move (0, row);
Driver.AddRune ('<');
for (int x = 0; x < bw; x++) {
SpecialChar special;
if (x < bx1 || x > bx2) {
special = SpecialChar.Stipple;
} else {
if (bx2 - bx1 == 0)
special = SpecialChar.Diamond;
else {
if (x == bx1)
special = SpecialChar.LeftTee;
else if (x == bx2)
special = SpecialChar.RightTee;
else
special = SpecialChar.HLine;
}
}
Driver.AddSpecial (special);
}
Driver.AddRune ('>');
}
}
}
}
/// <summary>
/// Scrollviews are views that present a window into a virtual space where children views are added. Similar to the iOS UIScrollView.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
@@ -15,11 +175,15 @@ namespace Terminal.Gui {
/// </remarks> /// </remarks>
public class ScrollView : View { public class ScrollView : View {
View contentView; View contentView;
ScrollBarView vertical, horizontal;
public ScrollView (Rect frame) : base (frame) public ScrollView (Rect frame) : base (frame)
{ {
contentView = new View (frame); contentView = new View (frame);
vertical = new ScrollBarView (new Rect (frame.Width - 1, 0, 1, frame.Height), frame.Height, 0, isVertical: true);
horizontal = new ScrollBarView (new Rect (0, frame.Height-1, frame.Width-1, 1), frame.Width-1, 0, isVertical: false);
base.Add (contentView); base.Add (contentView);
CanFocus = true;
} }
Size contentSize; Size contentSize;
@@ -38,6 +202,8 @@ namespace Terminal.Gui {
set { set {
contentSize = value; contentSize = value;
contentView.Frame = new Rect (contentOffset, value); contentView.Frame = new Rect (contentOffset, value);
vertical.Size = contentSize.Height;
horizontal.Size = contentSize.Width;
} }
} }
@@ -52,6 +218,8 @@ namespace Terminal.Gui {
set { set {
contentOffset = new Point (-value.X, -value.Y); contentOffset = new Point (-value.X, -value.Y);
contentView.Frame = new Rect (contentOffset, contentSize); contentView.Frame = new Rect (contentOffset, contentSize);
vertical.Position = Math.Max (0, -contentOffset.Y);
horizontal.Position = Math.Max (0, -contentOffset.X);
} }
} }
@@ -71,8 +239,15 @@ namespace Terminal.Gui {
public bool ShowHorizontalScrollIndicator { public bool ShowHorizontalScrollIndicator {
get => showHorizontalScrollIndicator; get => showHorizontalScrollIndicator;
set { set {
if (value == showHorizontalScrollIndicator)
return;
showHorizontalScrollIndicator = value; showHorizontalScrollIndicator = value;
SetNeedsDisplay (); SetNeedsDisplay ();
if (value)
base.Add (horizontal);
else
Remove (horizontal);
} }
} }
@@ -84,8 +259,15 @@ namespace Terminal.Gui {
public bool ShowVerticalScrollIndicator { public bool ShowVerticalScrollIndicator {
get => showVerticalScrollIndicator; get => showVerticalScrollIndicator;
set { set {
if (value == showVerticalScrollIndicator)
return;
showVerticalScrollIndicator = value; showVerticalScrollIndicator = value;
SetNeedsDisplay (); SetNeedsDisplay ();
if (value)
base.Add (vertical);
else
Remove (vertical);
} }
} }
@@ -98,70 +280,16 @@ namespace Terminal.Gui {
{ {
var oldClip = ClipToBounds (); var oldClip = ClipToBounds ();
base.Redraw(region); base.Redraw(region);
Attribute last = ColorScheme.Normal;
Driver.SetAttribute (last);
void SetColor (Attribute a)
{
if (a != last)
Driver.SetAttribute (a);
last = a;
}
Driver.Clip = oldClip; Driver.Clip = oldClip;
Driver.SetAttribute (ColorScheme.Normal);
}
if (true || ShowVerticalScrollIndicator) { public override void PositionCursor()
var bh = Bounds.Height; {
var by1 = -contentOffset.Y * bh/ contentSize.Height; if (Subviews.Count == 0)
var by2 = (-contentOffset.Y+bh) * bh/ contentSize.Height; Driver.Move (0, 0);
else
for (int y = 0; y < bh; y++) { base.PositionCursor ();
Move (Bounds.Width - 1, y);
SpecialChar special;
if (y < by1 || y > by2)
special = SpecialChar.Stipple;
else {
if (by2 - by1 == 0)
special = SpecialChar.Diamond;
else {
if (y == by1)
special = SpecialChar.TopTee;
else if (y == by2)
special = SpecialChar.BottomTee;
else
special = SpecialChar.VLine;
}
}
Driver.AddSpecial (special);
}
}
if (true || ShowHorizontalScrollIndicator){
var bw = Bounds.Width;
var bx1 = -contentOffset.X * bw / contentSize.Width;
var bx2 = (-contentOffset.X + bw) * bw / contentSize.Width;
Move (0, Bounds.Height - 1);
for (int x = 0; x < bw; x++) {
SpecialChar special;
if (x < bx1 || x > bx2){
special = SpecialChar.Stipple;
} else {
if (bx2 - bx1 == 0)
special = SpecialChar.Diamond;
else {
if (x == bx1)
special = SpecialChar.LeftTee;
else if (x == bx2)
special = SpecialChar.RightTee;
else
special = SpecialChar.HLine;
}
}
Driver.AddSpecial (special);
}
}
} }
} }
} }

View File

@@ -67,7 +67,9 @@ class Demo {
{ {
var scrollView = new ScrollView (new Rect (50, 10, 20, 8)) { var scrollView = new ScrollView (new Rect (50, 10, 20, 8)) {
ContentSize = new Size (100, 100), ContentSize = new Size (100, 100),
ContentOffset = new Point (5, -2) ContentOffset = new Point (5, -2),
ShowVerticalScrollIndicator = true,
ShowHorizontalScrollIndicator = true
}; };
//scrollView.Add (new Box10x (0, 0)); //scrollView.Add (new Box10x (0, 0));