Browse Source

Offers more simplicity to iterate with the ScrollBarView and its hosts.

BDisp 4 years ago
parent
commit
58c2509772

+ 1 - 1
Terminal.Gui/Views/ListView.cs

@@ -682,7 +682,7 @@ namespace Terminal.Gui {
 			if (selected < top) {
 			if (selected < top) {
 				top = selected;
 				top = selected;
 			} else if (selected >= top + Frame.Height) {
 			} else if (selected >= top + Frame.Height) {
-				top = Math.Max (selected - Frame.Height + 1, 0);
+				top = Math.Max (selected - Frame.Height + 2, 0);
 			}
 			}
 		}
 		}
 
 

+ 125 - 45
Terminal.Gui/Views/ScrollBarView.cs

@@ -27,9 +27,10 @@ namespace Terminal.Gui {
 		bool showScrollIndicator;
 		bool showScrollIndicator;
 		bool keepContentAlwaysInViewport = true;
 		bool keepContentAlwaysInViewport = true;
 		bool autoHideScrollBars = true;
 		bool autoHideScrollBars = true;
-		Dim originalHostWidth, originalHostHeight;
 		bool hosted;
 		bool hosted;
 		ScrollBarView otherScrollBarView;
 		ScrollBarView otherScrollBarView;
+		View contentBottomRightCorner;
+
 		bool showBothScrollIndicator => OtherScrollBarView != null && OtherScrollBarView.showScrollIndicator && showScrollIndicator;
 		bool showBothScrollIndicator => OtherScrollBarView != null && OtherScrollBarView.showScrollIndicator && showScrollIndicator;
 
 
 		/// <summary>
 		/// <summary>
@@ -69,7 +70,10 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Initializes a new instance of the <see cref="Gui.ScrollBarView"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// Initializes a new instance of the <see cref="Gui.ScrollBarView"/> class using <see cref="LayoutStyle.Computed"/> layout.
 		/// </summary>
 		/// </summary>
-		public ScrollBarView (View host, bool isVertical) : this (0, 0, isVertical)
+		/// <param name="host">The view that will host this scrollbar.</param>
+		/// <param name="isVertical">If set to <c>true</c> this is a vertical scrollbar, otherwise, the scrollbar is horizontal.</param>
+		/// <param name="showBothScrollIndicator">If set to <c>true (default)</c> will have the other scrollbar, otherwise will have only one.</param>
+		public ScrollBarView (View host, bool isVertical, bool showBothScrollIndicator = true) : this (0, 0, isVertical)
 		{
 		{
 			if (host == null) {
 			if (host == null) {
 				throw new ArgumentNullException ("The host parameter can't be null.");
 				throw new ArgumentNullException ("The host parameter can't be null.");
@@ -77,14 +81,43 @@ namespace Terminal.Gui {
 				throw new ArgumentNullException ("The host SuperView parameter can't be null.");
 				throw new ArgumentNullException ("The host SuperView parameter can't be null.");
 			}
 			}
 			hosted = true;
 			hosted = true;
-			originalHostWidth = host.Width;
-			originalHostHeight = host.Height;
-			X = isVertical ? Pos.Right(host) : Pos.Left (host);
-			Y = isVertical ? Pos.Top (host) : Pos.Bottom (host);
+			ColorScheme = host.ColorScheme;
+			X = isVertical ? Pos.Right (host) - 1 : Pos.Left (host);
+			Y = isVertical ? Pos.Top (host) : Pos.Bottom (host) - 1;
 			Host = host;
 			Host = host;
 			Host.SuperView.Add (this);
 			Host.SuperView.Add (this);
-			ShowScrollIndicator = true;
 			AutoHideScrollBars = true;
 			AutoHideScrollBars = true;
+			if (showBothScrollIndicator) {
+				OtherScrollBarView = new ScrollBarView (0, 0, !isVertical) {
+					ColorScheme = host.ColorScheme,
+					Host = host,
+					OtherScrollBarView = this,
+				};
+				OtherScrollBarView.X = OtherScrollBarView.IsVertical ? Pos.Right (host) - 1 : Pos.Left (host);
+				OtherScrollBarView.Y = OtherScrollBarView.IsVertical ? Pos.Top (host) : Pos.Bottom (host) - 1;
+				OtherScrollBarView.Host.SuperView.Add (OtherScrollBarView);
+				OtherScrollBarView.showScrollIndicator = true;
+			}
+			ShowScrollIndicator = true;
+			contentBottomRightCorner = new View (" ");
+			Host.SuperView.Add (contentBottomRightCorner);
+			contentBottomRightCorner.X = Pos.Right (host) - 1;
+			contentBottomRightCorner.Y = Pos.Bottom (host) - 1;
+			contentBottomRightCorner.Width = 1;
+			contentBottomRightCorner.Height = 1;
+			contentBottomRightCorner.MouseClick += ContentBottomRightCorner_MouseClick;
+		}
+
+		private void ContentBottomRightCorner_MouseClick (MouseEventArgs me)
+		{
+			if (me.MouseEvent.Flags == MouseFlags.WheeledDown || me.MouseEvent.Flags == MouseFlags.WheeledUp
+				|| me.MouseEvent.Flags == MouseFlags.WheeledRight || me.MouseEvent.Flags == MouseFlags.WheeledLeft) {
+				me.Handled = true;
+				MouseEvent (me.MouseEvent);
+			} else if (me.MouseEvent.Flags == MouseFlags.Button1Clicked) {
+				me.Handled = true;
+				Host.SetFocus ();
+			}
 		}
 		}
 
 
 		void Init (int size, int position, bool isVertical)
 		void Init (int size, int position, bool isVertical)
@@ -116,7 +149,6 @@ namespace Terminal.Gui {
 			get => size;
 			get => size;
 			set {
 			set {
 				size = value;
 				size = value;
-				ShowHideScrollBars ();
 				SetNeedsDisplay ();
 				SetNeedsDisplay ();
 			}
 			}
 		}
 		}
@@ -160,7 +192,7 @@ namespace Terminal.Gui {
 		public ScrollBarView OtherScrollBarView {
 		public ScrollBarView OtherScrollBarView {
 			get => otherScrollBarView;
 			get => otherScrollBarView;
 			set {
 			set {
-				if (value.IsVertical && vertical || !value.IsVertical && !vertical) {
+				if (value != null && (value.IsVertical && vertical || !value.IsVertical && !vertical)) {
 					throw new ArgumentException ($"There is already a {(vertical ? "vertical" : "horizontal")} ScrollBarView.");
 					throw new ArgumentException ($"There is already a {(vertical ? "vertical" : "horizontal")} ScrollBarView.");
 				}
 				}
 				otherScrollBarView = value;
 				otherScrollBarView = value;
@@ -186,13 +218,23 @@ namespace Terminal.Gui {
 					Visible = false;
 					Visible = false;
 					Position = 0;
 					Position = 0;
 				}
 				}
-				Width = vertical ? 1 : Dim.Width (Host);
-				Height = vertical ? Dim.Height (Host) : 1;
-				if (vertical) {
-					Host.Width = showScrollIndicator ? originalHostWidth - 1 : originalHostWidth;
-				} else {
-					Host.Height = showScrollIndicator ? originalHostHeight - 1 : originalHostHeight;
-				}
+				SetWidthHeight ();
+			}
+		}
+
+		void SetWidthHeight ()
+		{
+			if (showBothScrollIndicator) {
+				Width = vertical ? 1 : Dim.Width (Host) - 1;
+				Height = vertical ? Dim.Height (Host) - 1 : 1;
+				otherScrollBarView.Width = otherScrollBarView.vertical ? 1 : Dim.Width (Host) - 1;
+				otherScrollBarView.Height = otherScrollBarView.vertical ? Dim.Height (Host) - 1 : 1;
+			} else if (showScrollIndicator) {
+				Width = vertical ? 1 : Dim.Width (Host) - 0;
+				Height = vertical ? Dim.Height (Host) - 0 : 1;
+			} else if (otherScrollBarView != null && otherScrollBarView.showScrollIndicator) {
+				otherScrollBarView.Width = otherScrollBarView.vertical ? 1 : Dim.Width (Host) - 0;
+				otherScrollBarView.Height = otherScrollBarView.vertical ? Dim.Height (Host) - 0 : 1;
 			}
 			}
 		}
 		}
 
 
@@ -242,44 +284,69 @@ namespace Terminal.Gui {
 			ChangedPosition?.Invoke ();
 			ChangedPosition?.Invoke ();
 		}
 		}
 
 
-		internal bool pending;
+		/// <summary>
+		/// Only used for a hosted view that will update and redraw the scrollbars.
+		/// </summary>
+		public virtual void Refresh ()
+		{
+			ShowHideScrollBars ();
+		}
 
 
 		void ShowHideScrollBars ()
 		void ShowHideScrollBars ()
 		{
 		{
-			if (!hosted || !autoHideScrollBars) {
+			if (!hosted || (hosted && !autoHideScrollBars)) {
 				return;
 				return;
 			}
 			}
 
 
-			int barsize = vertical ? Bounds.Height : Bounds.Width;
+			var pending = CheckBothScrollBars (this);
+			CheckBothScrollBars (otherScrollBarView, pending);
+
+			SetWidthHeight ();
+			SetRelativeLayout (Bounds);
+			OtherScrollBarView.SetRelativeLayout (OtherScrollBarView.Bounds);
 
 
-			if (barsize == 0 || barsize > size) {
-				if (showScrollIndicator) {
-					ShowScrollIndicator = false;
+			if (showBothScrollIndicator) {
+				contentBottomRightCorner.Visible = true;
+			} else {
+				contentBottomRightCorner.Visible = false;
+			}
+			if (showBothScrollIndicator) {
+				Redraw (Bounds);
+			}
+			if (otherScrollBarView.showScrollIndicator) {
+				otherScrollBarView.Redraw (otherScrollBarView.Bounds);
+			}
+		}
+
+		bool CheckBothScrollBars (ScrollBarView scrollBarView, bool pending = false)
+		{
+			int barsize = scrollBarView.vertical ? scrollBarView.Bounds.Height : scrollBarView.Bounds.Width;
+
+			if (barsize == 0 || barsize > scrollBarView.size) {
+				if (scrollBarView.showScrollIndicator) {
+					scrollBarView.ShowScrollIndicator = false;
 				}
 				}
-			} else if (barsize > 0 && barsize == size && OtherScrollBarView != null && OtherScrollBarView.pending) {
-				if (showScrollIndicator) {
-					ShowScrollIndicator = false;
+			} else if (barsize > 0 && barsize == scrollBarView.size && scrollBarView.OtherScrollBarView != null && pending) {
+				if (scrollBarView.showScrollIndicator) {
+					scrollBarView.ShowScrollIndicator = false;
 				}
 				}
-				if (OtherScrollBarView != null && showBothScrollIndicator) {
-					OtherScrollBarView.ShowScrollIndicator = false;
+				if (scrollBarView.OtherScrollBarView != null && scrollBarView.showBothScrollIndicator) {
+					scrollBarView.OtherScrollBarView.ShowScrollIndicator = false;
 				}
 				}
-			} else if (barsize > 0 && barsize == size && OtherScrollBarView != null && !OtherScrollBarView.pending) {
+			} else if (barsize > 0 && barsize == size && scrollBarView.OtherScrollBarView != null && !pending) {
 				pending = true;
 				pending = true;
-				OtherScrollBarView.Redraw (OtherScrollBarView.Bounds);
 			} else {
 			} else {
-				if (OtherScrollBarView != null && OtherScrollBarView.pending) {
-					if (!showBothScrollIndicator) {
-						OtherScrollBarView.ShowScrollIndicator = true;
-						OtherScrollBarView.Redraw (OtherScrollBarView.Bounds);
+				if (scrollBarView.OtherScrollBarView != null && pending) {
+					if (!scrollBarView.showBothScrollIndicator) {
+						scrollBarView.OtherScrollBarView.ShowScrollIndicator = true;
 					}
 					}
 				}
 				}
-				if (!showScrollIndicator) {
-					ShowScrollIndicator = true;
+				if (!scrollBarView.showScrollIndicator) {
+					scrollBarView.ShowScrollIndicator = true;
 				}
 				}
 			}
 			}
-			if (OtherScrollBarView != null) {
-				OtherScrollBarView.pending = false;
-			}
+
+			return pending;
 		}
 		}
 
 
 		int posTopTee;
 		int posTopTee;
@@ -433,6 +500,10 @@ namespace Terminal.Gui {
 					Driver.AddRune (Driver.RightArrow);
 					Driver.AddRune (Driver.RightArrow);
 				}
 				}
 			}
 			}
+
+			if (hosted && showBothScrollIndicator) {
+				contentBottomRightCorner.Redraw (contentBottomRightCorner.Bounds);
+			}
 		}
 		}
 
 
 		int lastLocation = -1;
 		int lastLocation = -1;
@@ -454,8 +525,8 @@ namespace Terminal.Gui {
 
 
 			int location = vertical ? me.Y : me.X;
 			int location = vertical ? me.Y : me.X;
 			int barsize = vertical ? Bounds.Height : Bounds.Width;
 			int barsize = vertical ? Bounds.Height : Bounds.Width;
-			int posTopLeftTee = vertical ? posTopTee + 1: posLeftTee + 1;
-			int posBottomRightTee = vertical ? posBottomTee + 1: posRightTee + 1;
+			int posTopLeftTee = vertical ? posTopTee + 1 : posLeftTee + 1;
+			int posBottomRightTee = vertical ? posBottomTee + 1 : posRightTee + 1;
 			barsize -= 2;
 			barsize -= 2;
 			var pos = Position;
 			var pos = Position;
 
 
@@ -508,15 +579,24 @@ namespace Terminal.Gui {
 					} else if (me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)) {
 					} else if (me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)) {
 						var mb = (b2 - b1) / 2;
 						var mb = (b2 - b1) / 2;
 						var ml = mb + b1 + (mb == 0 ? 1 : 0);
 						var ml = mb + b1 + (mb == 0 ? 1 : 0);
-						if ((location >= b1 && location <= ml) || (location < lastLocation && lastLocation > -1)) {
+						if ((location > 1 || (location == 1 && posTopLeftTee > 1)) && ((location >= b1 && location <= ml) || (location < lastLocation && lastLocation > -1))) {
 							lastLocation = location;
 							lastLocation = location;
-							Position = b1 * Size / barsize;
-						} else if (location > lastLocation) {
 							var np = location * Size / barsize;
 							var np = location * Size / barsize;
-							CanScroll (np - pos, out int nv, vertical);
-							if (nv > 0) {
+							if (CanScroll (np - pos, out int nv, vertical)) {
+								Position = pos + nv;
+							}
+						} else if (location != barsize && location > lastLocation) {
+							var np = location * Size / barsize;
+							if (CanScroll (np - pos, out int nv, vertical)) {
 								Position = pos + nv;
 								Position = pos + nv;
 							}
 							}
+						} else if (location == 1 && posTopLeftTee <= 2) {
+							Position = 0;
+						} else if (location == barsize) {
+							CanScroll (Size - pos, out int nv, vertical);
+							if (nv > 0) {
+								Position = Math.Min (pos + nv, Size);
+							}
 						}
 						}
 					}
 					}
 				} else {
 				} else {

+ 17 - 25
UICatalog/Scenarios/Editor.cs

@@ -13,7 +13,7 @@ namespace UICatalog {
 		private string _fileName = "demo.txt";
 		private string _fileName = "demo.txt";
 		private TextView _textView;
 		private TextView _textView;
 		private bool _saved = true;
 		private bool _saved = true;
-		private ScrollBarView _vertical;
+		private ScrollBarView _scrollBar;
 
 
 		public override void Init (Toplevel top, ColorScheme colorScheme)
 		public override void Init (Toplevel top, ColorScheme colorScheme)
 		{
 		{
@@ -70,39 +70,31 @@ namespace UICatalog {
 
 
 			Win.Add (_textView);
 			Win.Add (_textView);
 
 
-			_vertical = new ScrollBarView (_textView, true);
-			var horizontal = new ScrollBarView (_textView, false);
-			_vertical.OtherScrollBarView = horizontal;
-			horizontal.OtherScrollBarView = _vertical;
+			_scrollBar = new ScrollBarView (_textView, true);
 
 
-			_vertical.ChangedPosition += () => {
-				_textView.TopRow = _vertical.Position;
-				if (_textView.TopRow != _vertical.Position) {
-					_vertical.Position = _textView.TopRow;
+			_scrollBar.ChangedPosition += () => {
+				_textView.TopRow = _scrollBar.Position;
+				if (_textView.TopRow != _scrollBar.Position) {
+					_scrollBar.Position = _textView.TopRow;
 				}
 				}
 				_textView.SetNeedsDisplay ();
 				_textView.SetNeedsDisplay ();
 			};
 			};
 
 
-			horizontal.ChangedPosition += () => {
-				_textView.LeftColumn = horizontal.Position;
-				if (_textView.LeftColumn != horizontal.Position) {
-					horizontal.Position = _textView.LeftColumn;
+			_scrollBar.OtherScrollBarView.ChangedPosition += () => {
+				_textView.LeftColumn = _scrollBar.OtherScrollBarView.Position;
+				if (_textView.LeftColumn != _scrollBar.OtherScrollBarView.Position) {
+					_scrollBar.OtherScrollBarView.Position = _textView.LeftColumn;
 				}
 				}
 				_textView.SetNeedsDisplay ();
 				_textView.SetNeedsDisplay ();
 			};
 			};
 
 
 			_textView.DrawContent += (e) => {
 			_textView.DrawContent += (e) => {
-				_vertical.Size = _textView.Lines - 1;
-				_vertical.Position = _textView.TopRow;
-				horizontal.Size = _textView.Maxlength + 1;
-				horizontal.Position = _textView.LeftColumn;
-				_vertical.ColorScheme = horizontal.ColorScheme = _textView.ColorScheme;
-				if (_vertical.ShowScrollIndicator) {
-					_vertical.Redraw (e);
-				}
-				if (horizontal.ShowScrollIndicator) {
-					horizontal.Redraw (e);
-				}
+				_scrollBar.Size = _textView.Lines;
+				_scrollBar.Position = _textView.TopRow;
+				_scrollBar.OtherScrollBarView.Size = _textView.Maxlength + 1;
+				_scrollBar.OtherScrollBarView.Position = _textView.LeftColumn;
+				_scrollBar.LayoutSubviews ();
+				_scrollBar.Refresh ();
 			};
 			};
 		}
 		}
 
 
@@ -196,7 +188,7 @@ namespace UICatalog {
 			item.Title = "Keep Content Always In Viewport";
 			item.Title = "Keep Content Always In Viewport";
 			item.CheckType |= MenuItemCheckStyle.Checked;
 			item.CheckType |= MenuItemCheckStyle.Checked;
 			item.Checked = true;
 			item.Checked = true;
-			item.Action += () => _vertical.KeepContentAlwaysInViewport = item.Checked = !item.Checked;
+			item.Action += () => _scrollBar.KeepContentAlwaysInViewport = item.Checked = !item.Checked;
 
 
 			return new MenuItem [] { item };
 			return new MenuItem [] { item };
 		}
 		}

+ 17 - 26
UICatalog/Scenarios/ListViewWithSelection.cs

@@ -55,49 +55,40 @@ namespace UICatalog {
 			};
 			};
 			Win.Add (_listView);
 			Win.Add (_listView);
 
 
-			var vertical = new ScrollBarView (_listView, true);
-			var horizontal = new ScrollBarView (_listView, false);
-			vertical.OtherScrollBarView = horizontal;
-			horizontal.OtherScrollBarView = vertical;
-
-			vertical.ChangedPosition += () => {
-				_listView.TopItem = vertical.Position;
-				if (_listView.TopItem != vertical.Position) {
-					vertical.Position = _listView.TopItem;
+			var _scrollBar = new ScrollBarView (_listView, true);
+
+			_scrollBar.ChangedPosition += () => {
+				_listView.TopItem = _scrollBar.Position;
+				if (_listView.TopItem != _scrollBar.Position) {
+					_scrollBar.Position = _listView.TopItem;
 				}
 				}
 				_listView.SetNeedsDisplay ();
 				_listView.SetNeedsDisplay ();
 			};
 			};
 
 
-			horizontal.ChangedPosition += () => {
-				_listView.LeftItem = horizontal.Position;
-				if (_listView.LeftItem != horizontal.Position) {
-					horizontal.Position = _listView.LeftItem;
+			_scrollBar.OtherScrollBarView.ChangedPosition += () => {
+				_listView.LeftItem = _scrollBar.OtherScrollBarView.Position;
+				if (_listView.LeftItem != _scrollBar.OtherScrollBarView.Position) {
+					_scrollBar.OtherScrollBarView.Position = _listView.LeftItem;
 				}
 				}
 				_listView.SetNeedsDisplay ();
 				_listView.SetNeedsDisplay ();
 			};
 			};
 
 
 			_listView.DrawContent += (e) => {
 			_listView.DrawContent += (e) => {
-				vertical.Size = _listView.Source.Count - 1;
-				vertical.Position = _listView.TopItem;
-				horizontal.Size = _listView.Maxlength;
-				horizontal.Position = _listView.LeftItem;
-				vertical.ColorScheme = horizontal.ColorScheme = _listView.ColorScheme;
-				if (vertical.ShowScrollIndicator) {
-					vertical.Redraw (e);
-				}
-				if (horizontal.ShowScrollIndicator) {
-					horizontal.Redraw (e);
-				}
+				_scrollBar.Size = _listView.Source.Count;
+				_scrollBar.Position = _listView.TopItem;
+				_scrollBar.OtherScrollBarView.Size = _listView.Maxlength;
+				_scrollBar.OtherScrollBarView.Position = _listView.LeftItem;
+				_scrollBar.Refresh ();
 			};
 			};
 
 
 			_listView.SetSource (_scenarios);
 			_listView.SetSource (_scenarios);
 
 
 			var k = "Keep Content Always In Viewport";
 			var k = "Keep Content Always In Viewport";
-			var keepCheckBox = new CheckBox (k, vertical.AutoHideScrollBars) {
+			var keepCheckBox = new CheckBox (k, _scrollBar.AutoHideScrollBars) {
 				X = Pos.AnchorEnd (k.Length + 3),
 				X = Pos.AnchorEnd (k.Length + 3),
 				Y = 0,
 				Y = 0,
 			};
 			};
-			keepCheckBox.Toggled += (_) => vertical.KeepContentAlwaysInViewport = keepCheckBox.Checked;
+			keepCheckBox.Toggled += (_) => _scrollBar.KeepContentAlwaysInViewport = keepCheckBox.Checked;
 			Win.Add (keepCheckBox);
 			Win.Add (keepCheckBox);
 		}
 		}
 
 

+ 14 - 23
UICatalog/Scenarios/ListsAndCombos.cs

@@ -39,39 +39,30 @@ namespace UICatalog.Scenarios {
 			listview.SelectedItemChanged += (ListViewItemEventArgs e) => lbListView.Text = items [listview.SelectedItem];
 			listview.SelectedItemChanged += (ListViewItemEventArgs e) => lbListView.Text = items [listview.SelectedItem];
 			Win.Add (lbListView, listview);
 			Win.Add (lbListView, listview);
 
 
-			var vertical = new ScrollBarView (listview, true);
-			var horizontal = new ScrollBarView (listview, false);
-			vertical.OtherScrollBarView = horizontal;
-			horizontal.OtherScrollBarView = vertical;
+			var _scrollBar = new ScrollBarView (listview, true);
 
 
-			vertical.ChangedPosition += () => {
-				listview.TopItem = vertical.Position;
-				if (listview.TopItem != vertical.Position) {
-					vertical.Position = listview.TopItem;
+			_scrollBar.ChangedPosition += () => {
+				listview.TopItem = _scrollBar.Position;
+				if (listview.TopItem != _scrollBar.Position) {
+					_scrollBar.Position = listview.TopItem;
 				}
 				}
 				listview.SetNeedsDisplay ();
 				listview.SetNeedsDisplay ();
 			};
 			};
 
 
-			horizontal.ChangedPosition += () => {
-				listview.LeftItem = horizontal.Position;
-				if (listview.LeftItem != horizontal.Position) {
-					horizontal.Position = listview.LeftItem;
+			_scrollBar.OtherScrollBarView.ChangedPosition += () => {
+				listview.LeftItem = _scrollBar.OtherScrollBarView.Position;
+				if (listview.LeftItem != _scrollBar.OtherScrollBarView.Position) {
+					_scrollBar.OtherScrollBarView.Position = listview.LeftItem;
 				}
 				}
 				listview.SetNeedsDisplay ();
 				listview.SetNeedsDisplay ();
 			};
 			};
 
 
 			listview.DrawContent += (e) => {
 			listview.DrawContent += (e) => {
-				vertical.Size = listview.Source.Count - 1;
-				vertical.Position = listview.TopItem;
-				horizontal.Size = listview.Maxlength;
-				horizontal.Position = listview.LeftItem;
-				vertical.ColorScheme = horizontal.ColorScheme = listview.ColorScheme;
-				if (vertical.ShowScrollIndicator) {
-					vertical.Redraw (e);
-				}
-				if (horizontal.ShowScrollIndicator) {
-					horizontal.Redraw (e);
-				}
+				_scrollBar.Size = listview.Source.Count;
+				_scrollBar.Position = listview.TopItem;
+				_scrollBar.OtherScrollBarView.Size = listview.Maxlength;
+				_scrollBar.OtherScrollBarView.Position = listview.LeftItem;
+				_scrollBar.Refresh ();
 			};
 			};
 
 
 			// ComboBox
 			// ComboBox

+ 129 - 85
UnitTests/ScrollBarViewTests.cs

@@ -11,8 +11,7 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		private HostView _hostView;
 		private HostView _hostView;
-		private ScrollBarView _vertical;
-		private ScrollBarView _horizontal;
+		private ScrollBarView _scrollBar;
 		private bool _added;
 		private bool _added;
 
 
 		public ScrollBarViewTests ()
 		public ScrollBarViewTests ()
@@ -37,8 +36,8 @@ namespace Terminal.Gui {
 		{
 		{
 			if (!_added) {
 			if (!_added) {
 				_hostView.DrawContent += _hostView_DrawContent;
 				_hostView.DrawContent += _hostView_DrawContent;
-				_vertical.ChangedPosition += _vertical_ChangedPosition;
-				_horizontal.ChangedPosition += _horizontal_ChangedPosition;
+				_scrollBar.ChangedPosition += _scrollBar_ChangedPosition;
+				_scrollBar.OtherScrollBarView.ChangedPosition += _scrollBar_OtherScrollBarView_ChangedPosition;
 			}
 			}
 			_added = true;
 			_added = true;
 		}
 		}
@@ -47,41 +46,36 @@ namespace Terminal.Gui {
 		{
 		{
 			if (_added) {
 			if (_added) {
 				_hostView.DrawContent -= _hostView_DrawContent;
 				_hostView.DrawContent -= _hostView_DrawContent;
-				_vertical.ChangedPosition -= _vertical_ChangedPosition;
-				_horizontal.ChangedPosition -= _horizontal_ChangedPosition;
+				_scrollBar.ChangedPosition -= _scrollBar_ChangedPosition;
+				_scrollBar.OtherScrollBarView.ChangedPosition -= _scrollBar_OtherScrollBarView_ChangedPosition;
 			}
 			}
 			_added = false;
 			_added = false;
 		}
 		}
 
 
 		private void _hostView_DrawContent (Rect obj)
 		private void _hostView_DrawContent (Rect obj)
 		{
 		{
-			_vertical.Size = _hostView.Lines;
-			_vertical.Position = _hostView.Top;
-			_horizontal.Size = _hostView.Cols;
-			_horizontal.Position = _hostView.Left;
-			_vertical.ColorScheme = _horizontal.ColorScheme = _hostView.ColorScheme;
-			if (_vertical.ShowScrollIndicator) {
-				_vertical.Redraw (obj);
-			}
-			if (_horizontal.ShowScrollIndicator) {
-				_horizontal.Redraw (obj);
-			}
+			_scrollBar.Size = _hostView.Lines;
+			_scrollBar.Position = _hostView.Top;
+			_scrollBar.OtherScrollBarView.Size = _hostView.Cols;
+			_scrollBar.OtherScrollBarView.Position = _hostView.Left;
+			_scrollBar.ColorScheme = _scrollBar.OtherScrollBarView.ColorScheme = _hostView.ColorScheme;
+			_scrollBar.Refresh ();
 		}
 		}
 
 
-		private void _vertical_ChangedPosition ()
+		private void _scrollBar_ChangedPosition ()
 		{
 		{
-			_hostView.Top = _vertical.Position;
-			if (_hostView.Top != _vertical.Position) {
-				_vertical.Position = _hostView.Top;
+			_hostView.Top = _scrollBar.Position;
+			if (_hostView.Top != _scrollBar.Position) {
+				_scrollBar.Position = _hostView.Top;
 			}
 			}
 			_hostView.SetNeedsDisplay ();
 			_hostView.SetNeedsDisplay ();
 		}
 		}
 
 
-		private void _horizontal_ChangedPosition ()
+		private void _scrollBar_OtherScrollBarView_ChangedPosition ()
 		{
 		{
-			_hostView.Left = _horizontal.Position;
-			if (_hostView.Left != _horizontal.Position) {
-				_horizontal.Position = _hostView.Left;
+			_hostView.Left = _scrollBar.OtherScrollBarView.Position;
+			if (_hostView.Left != _scrollBar.OtherScrollBarView.Position) {
+				_scrollBar.OtherScrollBarView.Position = _hostView.Left;
 			}
 			}
 			_hostView.SetNeedsDisplay ();
 			_hostView.SetNeedsDisplay ();
 		}
 		}
@@ -145,27 +139,27 @@ namespace Terminal.Gui {
 		{
 		{
 			RemoveHandlers ();
 			RemoveHandlers ();
 
 
-			_vertical = new ScrollBarView (_hostView, true);
-			_horizontal = new ScrollBarView (_hostView, false);
-			_vertical.OtherScrollBarView = _horizontal;
-			_horizontal.OtherScrollBarView = _vertical;
+			_scrollBar = new ScrollBarView (_hostView, true);
+			_scrollBar.OtherScrollBarView = new ScrollBarView (_hostView, false);
+			_scrollBar.OtherScrollBarView = _scrollBar.OtherScrollBarView;
+			_scrollBar.OtherScrollBarView.OtherScrollBarView = _scrollBar;
 
 
-			Assert.True (_vertical.IsVertical);
-			Assert.False (_horizontal.IsVertical);
+			Assert.True (_scrollBar.IsVertical);
+			Assert.False (_scrollBar.OtherScrollBarView.IsVertical);
 
 
-			Assert.Equal (_vertical.Position, _hostView.Top);
-			Assert.NotEqual (_vertical.Size, _hostView.Lines);
-			Assert.Equal (_horizontal.Position, _hostView.Left);
-			Assert.NotEqual (_horizontal.Size, _hostView.Cols);
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
+			Assert.NotEqual (_scrollBar.Size, _hostView.Lines);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
+			Assert.NotEqual (_scrollBar.OtherScrollBarView.Size, _hostView.Cols);
 
 
 			AddHandlers ();
 			AddHandlers ();
 			_hostView.SuperView.LayoutSubviews ();
 			_hostView.SuperView.LayoutSubviews ();
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
 
 
-			Assert.Equal (_vertical.Position, _hostView.Top);
-			Assert.Equal (_vertical.Size, _hostView.Lines);
-			Assert.Equal (_horizontal.Position, _hostView.Left);
-			Assert.Equal (_horizontal.Size, _hostView.Cols);
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
+			Assert.Equal (_scrollBar.Size, _hostView.Lines);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Size, _hostView.Cols);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -175,11 +169,11 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			_vertical.Position = 2;
-			Assert.Equal (_vertical.Position, _hostView.Top);
+			_scrollBar.Position = 2;
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
 
 
-			_horizontal.Position = 5;
-			Assert.Equal (_horizontal.Position, _hostView.Left);
+			_scrollBar.OtherScrollBarView.Position = 5;
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -189,22 +183,22 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			for (int i = 0; i < _vertical.Size; i++) {
-				_vertical.Position += 1;
-				Assert.Equal (_vertical.Position, _hostView.Top);
+			for (int i = 0; i < _scrollBar.Size; i++) {
+				_scrollBar.Position += 1;
+				Assert.Equal (_scrollBar.Position, _hostView.Top);
 			}
 			}
-			for (int i = _vertical.Size - 1; i >= 0; i--) {
-				_vertical.Position -= 1;
-				Assert.Equal (_vertical.Position, _hostView.Top);
+			for (int i = _scrollBar.Size - 1; i >= 0; i--) {
+				_scrollBar.Position -= 1;
+				Assert.Equal (_scrollBar.Position, _hostView.Top);
 			}
 			}
 
 
-			for (int i = 0; i < _horizontal.Size; i++) {
-				_horizontal.Position += i;
-				Assert.Equal (_horizontal.Position, _hostView.Left);
+			for (int i = 0; i < _scrollBar.OtherScrollBarView.Size; i++) {
+				_scrollBar.OtherScrollBarView.Position += i;
+				Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
 			}
 			}
-			for (int i = _horizontal.Size - 1; i >= 0; i--) {
-				_horizontal.Position -= 1;
-				Assert.Equal (_horizontal.Position, _hostView.Left);
+			for (int i = _scrollBar.OtherScrollBarView.Size - 1; i >= 0; i--) {
+				_scrollBar.OtherScrollBarView.Position -= 1;
+				Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
 			}
 			}
 		}
 		}
 
 
@@ -215,13 +209,13 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			_vertical.Position = -20;
-			Assert.Equal (0, _vertical.Position);
-			Assert.Equal (_vertical.Position, _hostView.Top);
+			_scrollBar.Position = -20;
+			Assert.Equal (0, _scrollBar.Position);
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
 
 
-			_horizontal.Position = -50;
-			Assert.Equal (0, _horizontal.Position);
-			Assert.Equal (_horizontal.Position, _hostView.Left);
+			_scrollBar.OtherScrollBarView.Position = -50;
+			Assert.Equal (0, _scrollBar.OtherScrollBarView.Position);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -233,11 +227,11 @@ namespace Terminal.Gui {
 
 
 			_hostView.Top = 3;
 			_hostView.Top = 3;
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
-			Assert.Equal (_vertical.Position, _hostView.Top);
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
 
 
 			_hostView.Left = 6;
 			_hostView.Left = 6;
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
-			Assert.Equal (_horizontal.Position, _hostView.Left);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -247,8 +241,8 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			Assert.Equal (_vertical.OtherScrollBarView, _horizontal);
-			Assert.Equal (_horizontal.OtherScrollBarView, _vertical);
+			Assert.Equal (_scrollBar.OtherScrollBarView, _scrollBar.OtherScrollBarView);
+			Assert.Equal (_scrollBar.OtherScrollBarView.OtherScrollBarView, _scrollBar);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -258,8 +252,8 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			Assert.True (_vertical.ShowScrollIndicator);
-			Assert.True (_horizontal.ShowScrollIndicator);
+			Assert.True (_scrollBar.ShowScrollIndicator);
+			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -269,13 +263,28 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			_vertical.Position = 50;
-			Assert.Equal (_vertical.Position, _vertical.Size - _vertical.Bounds.Height + 1);
-			Assert.Equal (_vertical.Position, _hostView.Top);
-
-			_horizontal.Position = 150;
-			Assert.Equal (_horizontal.Position, _horizontal.Size - _horizontal.Bounds.Width + 1);
-			Assert.Equal (_horizontal.Position, _hostView.Left);
+			Assert.Equal (80, _hostView.Bounds.Width);
+			Assert.Equal (25, _hostView.Bounds.Height);
+			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
+			Assert.Equal (24, _scrollBar.Bounds.Height);
+			Assert.Equal (30, _scrollBar.Size);
+			Assert.Equal (100, _scrollBar.OtherScrollBarView.Size);
+			Assert.True (_scrollBar.ShowScrollIndicator);
+			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
+			Assert.True (_scrollBar.Visible);
+			Assert.True (_scrollBar.OtherScrollBarView.Visible);
+
+			_scrollBar.Position = 50;
+			Assert.Equal (_scrollBar.Position, _scrollBar.Size - _scrollBar.Bounds.Height);
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
+			Assert.Equal (6, _scrollBar.Position);
+			Assert.Equal (6, _hostView.Top);
+
+			_scrollBar.OtherScrollBarView.Position = 150;
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _scrollBar.OtherScrollBarView.Size - _scrollBar.OtherScrollBarView.Bounds.Width);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
+			Assert.Equal (21, _scrollBar.OtherScrollBarView.Position);
+			Assert.Equal (21, _hostView.Left);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -285,14 +294,14 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
-			_vertical.KeepContentAlwaysInViewport = false;
-			_vertical.Position = 50;
-			Assert.Equal (_vertical.Position, _vertical.Size - 1);
-			Assert.Equal (_vertical.Position, _hostView.Top);
+			_scrollBar.KeepContentAlwaysInViewport = false;
+			_scrollBar.Position = 50;
+			Assert.Equal (_scrollBar.Position, _scrollBar.Size - 1);
+			Assert.Equal (_scrollBar.Position, _hostView.Top);
 
 
-			_horizontal.Position = 150;
-			Assert.Equal (_horizontal.Position, _horizontal.Size - 1);
-			Assert.Equal (_horizontal.Position, _hostView.Left);
+			_scrollBar.OtherScrollBarView.Position = 150;
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _scrollBar.OtherScrollBarView.Size - 1);
+			Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -302,19 +311,54 @@ namespace Terminal.Gui {
 
 
 			AddHandlers ();
 			AddHandlers ();
 
 
+			_hostView.Redraw (_hostView.Bounds);
+			Assert.True (_scrollBar.ShowScrollIndicator);
+			Assert.True (_scrollBar.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+				_scrollBar.Height.ToString ());
+			Assert.Equal (24, _scrollBar.Bounds.Height);
+			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
+			Assert.True (_scrollBar.OtherScrollBarView.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+				_scrollBar.OtherScrollBarView.Width.ToString ());
+			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
+
 			_hostView.Lines = 10;
 			_hostView.Lines = 10;
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
-			Assert.False (_vertical.ShowScrollIndicator);
+			Assert.False (_scrollBar.ShowScrollIndicator);
+			Assert.False (_scrollBar.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+				_scrollBar.Height.ToString ());
+			Assert.Equal (24, _scrollBar.Bounds.Height);
+
 			_hostView.Cols = 60;
 			_hostView.Cols = 60;
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
-			Assert.False (_horizontal.ShowScrollIndicator);
+			Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
+			Assert.False (_scrollBar.OtherScrollBarView.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
+				_scrollBar.OtherScrollBarView.Width.ToString ());
+			Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width);
 
 
 			_hostView.Lines = 40;
 			_hostView.Lines = 40;
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
-			Assert.True (_vertical.ShowScrollIndicator);
+			Assert.True (_scrollBar.ShowScrollIndicator);
+			Assert.True (_scrollBar.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(0))",
+				_scrollBar.Height.ToString ());
+			Assert.Equal (25, _scrollBar.Bounds.Height);
+
 			_hostView.Cols = 120;
 			_hostView.Cols = 120;
 			_hostView.Redraw (_hostView.Bounds);
 			_hostView.Redraw (_hostView.Bounds);
-			Assert.True (_horizontal.ShowScrollIndicator);
+			Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator);
+			Assert.True (_scrollBar.OtherScrollBarView.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Width, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+				_scrollBar.OtherScrollBarView.Width.ToString ());
+			Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width);
+			Assert.True (_scrollBar.ShowScrollIndicator);
+			Assert.True (_scrollBar.Visible);
+			Assert.Equal ("Dim.Combine(DimView(side=Height, target=HostView()({X=0,Y=0,Width=80,Height=25}))-Dim.Absolute(1))",
+				_scrollBar.Height.ToString ());
+			Assert.Equal (24, _scrollBar.Bounds.Height);
 		}
 		}
 	}
 	}
 }
 }