using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using Xunit; using Xunit.Abstractions; namespace Terminal.Gui.Views { public class ScrollBarViewTests { readonly ITestOutputHelper output; public ScrollBarViewTests (ITestOutputHelper output) { this.output = output; } // This class enables test functions annotated with the [InitShutdown] attribute // to have a function called before the test function is called and after. // // This is necessary because a) Application is a singleton and Init/Shutdown must be called // as a pair, and b) all unit test functions should be atomic. [AttributeUsage (AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class InitShutdownAttribute : Xunit.Sdk.BeforeAfterTestAttribute { public override void Before (MethodInfo methodUnderTest) { Debug.WriteLine ($"Before: {methodUnderTest.Name}"); if (_hostView != null) { throw new InvalidOperationException ("After did not run."); } Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))); var top = Application.Top; ScrollBarViewTests._hostView = new HostView () { Width = Dim.Fill (), Height = Dim.Fill (), Top = 0, Lines = 30, Left = 0, Cols = 100 }; top.Add (ScrollBarViewTests._hostView); } public override void After (MethodInfo methodUnderTest) { Debug.WriteLine ($"After: {methodUnderTest.Name}"); ScrollBarViewTests._hostView = null; Application.Shutdown (); } } public class HostView : View { public int Top { get; set; } public int Lines { get; set; } public int Left { get; set; } public int Cols { get; set; } } private static HostView _hostView; private ScrollBarView _scrollBar; private bool _added; private void AddHandlers () { if (!_added) { _hostView.DrawContent += _hostView_DrawContent; _scrollBar.ChangedPosition += _scrollBar_ChangedPosition; _scrollBar.OtherScrollBarView.ChangedPosition += _scrollBar_OtherScrollBarView_ChangedPosition; } _added = true; } private void RemoveHandlers () { if (_added) { _hostView.DrawContent -= _hostView_DrawContent; _scrollBar.ChangedPosition -= _scrollBar_ChangedPosition; _scrollBar.OtherScrollBarView.ChangedPosition -= _scrollBar_OtherScrollBarView_ChangedPosition; } _added = false; } private void _hostView_DrawContent (Rect obj) { _scrollBar.Size = _hostView.Lines; _scrollBar.Position = _hostView.Top; _scrollBar.OtherScrollBarView.Size = _hostView.Cols; _scrollBar.OtherScrollBarView.Position = _hostView.Left; _scrollBar.Refresh (); } private void _scrollBar_ChangedPosition () { _hostView.Top = _scrollBar.Position; if (_hostView.Top != _scrollBar.Position) { _scrollBar.Position = _hostView.Top; } _hostView.SetNeedsDisplay (); } private void _scrollBar_OtherScrollBarView_ChangedPosition () { _hostView.Left = _scrollBar.OtherScrollBarView.Position; if (_hostView.Left != _scrollBar.OtherScrollBarView.Position) { _scrollBar.OtherScrollBarView.Position = _hostView.Left; } _hostView.SetNeedsDisplay (); } [Fact] [InitShutdown] public void Hosting_A_Null_View_To_A_ScrollBarView_Throws_ArgumentNullException () { Assert.Throws ("The host parameter can't be null.", () => new ScrollBarView (null, true)); Assert.Throws ("The host parameter can't be null.", () => new ScrollBarView (null, false)); } [Fact] [InitShutdown] public void Hosting_A_Null_SuperView_View_To_A_ScrollBarView_Throws_ArgumentNullException () { Assert.Throws ("The host SuperView parameter can't be null.", () => new ScrollBarView (new View (), true)); Assert.Throws ("The host SuperView parameter can't be null.", () => new ScrollBarView (new View (), false)); } [Fact] [InitShutdown] public void Hosting_Two_Vertical_ScrollBarView_Throws_ArgumentException () { var top = new Toplevel (); var host = new View (); top.Add (host); var v = new ScrollBarView (host, true); var h = new ScrollBarView (host, true); Assert.Throws (() => v.OtherScrollBarView = h); Assert.Throws (() => h.OtherScrollBarView = v); } [Fact] [InitShutdown] public void Hosting_Two_Horizontal_ScrollBarView_Throws_ArgumentException () { var top = new Toplevel (); var host = new View (); top.Add (host); var v = new ScrollBarView (host, false); var h = new ScrollBarView (host, false); Assert.Throws (() => v.OtherScrollBarView = h); Assert.Throws (() => h.OtherScrollBarView = v); } [Fact] [InitShutdown] public void Scrolling_With_Default_Constructor_Do_Not_Scroll () { var sbv = new ScrollBarView { Position = 1 }; Assert.NotEqual (1, sbv.Position); Assert.Equal (0, sbv.Position); } [Fact] [InitShutdown] public void Hosting_A_View_To_A_ScrollBarView () { RemoveHandlers (); _scrollBar = new ScrollBarView (_hostView, true); Assert.True (_scrollBar.IsVertical); Assert.False (_scrollBar.OtherScrollBarView.IsVertical); 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 (); _hostView.SuperView.LayoutSubviews (); _hostView.Redraw (_hostView.Bounds); 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] [InitShutdown] public void ChangedPosition_Update_The_Hosted_View () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); _scrollBar.Position = 2; Assert.Equal (_scrollBar.Position, _hostView.Top); _scrollBar.OtherScrollBarView.Position = 5; Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left); } [Fact] [InitShutdown] public void ChangedPosition_Scrolling () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); for (int i = 0; i < _scrollBar.Size; i++) { _scrollBar.Position += 1; Assert.Equal (_scrollBar.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 < _scrollBar.OtherScrollBarView.Size; i++) { _scrollBar.OtherScrollBarView.Position += i; Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left); } for (int i = _scrollBar.OtherScrollBarView.Size - 1; i >= 0; i--) { _scrollBar.OtherScrollBarView.Position -= 1; Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left); } } [Fact] [InitShutdown] public void ChangedPosition_Negative_Value () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); _scrollBar.Position = -20; Assert.Equal (0, _scrollBar.Position); Assert.Equal (_scrollBar.Position, _hostView.Top); _scrollBar.OtherScrollBarView.Position = -50; Assert.Equal (0, _scrollBar.OtherScrollBarView.Position); Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left); } [Fact] [InitShutdown] public void DrawContent_Update_The_ScrollBarView_Position () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); _hostView.Top = 3; _hostView.Redraw (_hostView.Bounds); Assert.Equal (_scrollBar.Position, _hostView.Top); _hostView.Left = 6; _hostView.Redraw (_hostView.Bounds); Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left); } [Fact] [InitShutdown] public void OtherScrollBarView_Not_Null () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); Assert.NotNull (_scrollBar.OtherScrollBarView); Assert.NotEqual (_scrollBar, _scrollBar.OtherScrollBarView); Assert.Equal (_scrollBar.OtherScrollBarView.OtherScrollBarView, _scrollBar); } [Fact] [InitShutdown] public void ShowScrollIndicator_Check () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); } [Fact] [InitShutdown] public void KeepContentAlwaysInViewport_True () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); 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); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.Visible); Assert.True (_scrollBar.OtherScrollBarView.Visible); _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); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.Visible); Assert.True (_scrollBar.OtherScrollBarView.Visible); } [Fact] [InitShutdown] public void KeepContentAlwaysInViewport_False () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); _scrollBar.KeepContentAlwaysInViewport = false; _scrollBar.Position = 50; Assert.Equal (_scrollBar.Position, _scrollBar.Size - 1); Assert.Equal (_scrollBar.Position, _hostView.Top); Assert.Equal (29, _scrollBar.Position); Assert.Equal (29, _hostView.Top); _scrollBar.OtherScrollBarView.Position = 150; Assert.Equal (_scrollBar.OtherScrollBarView.Position, _scrollBar.OtherScrollBarView.Size - 1); Assert.Equal (_scrollBar.OtherScrollBarView.Position, _hostView.Left); Assert.Equal (99, _scrollBar.OtherScrollBarView.Position); Assert.Equal (99, _hostView.Left); } [Fact] [InitShutdown] public void AutoHideScrollBars_Check () { Hosting_A_View_To_A_ScrollBarView (); AddHandlers (); _hostView.Redraw (_hostView.Bounds); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.Visible); Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); 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); Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Lines = 10; _hostView.Redraw (_hostView.Bounds); Assert.False (_scrollBar.ShowScrollIndicator); Assert.False (_scrollBar.Visible); Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); 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(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Cols = 60; _hostView.Redraw (_hostView.Bounds); Assert.False (_scrollBar.ShowScrollIndicator); Assert.False (_scrollBar.Visible); Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); 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.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); Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Lines = 40; _hostView.Redraw (_hostView.Bounds); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.Visible); Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); 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); 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); Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Cols = 120; _hostView.Redraw (_hostView.Bounds); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.Visible); Assert.Equal ("Dim.Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); 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); Assert.Equal ("Dim.Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); } [Fact] public void Constructor_ShowBothScrollIndicator_False_And_IsVertical_True_Refresh_Does_Not_Throws_An_Object_Null_Exception () { var exception = Record.Exception (() => { Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))); var top = Application.Top; var win = new Window () { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; List source = new List (); for (int i = 0; i < 50; i++) { source.Add ($"item {i}"); } var listView = new ListView (source) { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (listView); var newScrollBarView = new ScrollBarView (listView, true, false) { KeepContentAlwaysInViewport = true }; win.Add (newScrollBarView); newScrollBarView.ChangedPosition += () => { listView.TopItem = newScrollBarView.Position; if (listView.TopItem != newScrollBarView.Position) { newScrollBarView.Position = listView.TopItem; } Assert.Equal (newScrollBarView.Position, listView.TopItem); listView.SetNeedsDisplay (); }; listView.DrawContent += (e) => { newScrollBarView.Size = listView.Source.Count; Assert.Equal (newScrollBarView.Size, listView.Source.Count); newScrollBarView.Position = listView.TopItem; Assert.Equal (newScrollBarView.Position, listView.TopItem); newScrollBarView.Refresh (); }; top.Ready += () => { newScrollBarView.Position = 45; Assert.Equal (newScrollBarView.Position, newScrollBarView.Size - listView.TopItem + (listView.TopItem - listView.Bounds.Height)); Assert.Equal (newScrollBarView.Position, listView.TopItem); Assert.Equal (27, newScrollBarView.Position); Assert.Equal (27, listView.TopItem); Application.RequestStop (); }; top.Add (win); Application.Run (); Application.Shutdown (); }); Assert.Null (exception); } [Fact] public void Constructor_ShowBothScrollIndicator_False_And_IsVertical_False_Refresh_Does_Not_Throws_An_Object_Null_Exception () { var exception = Record.Exception (() => { Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true))); var top = Application.Top; var win = new Window () { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; List source = new List (); for (int i = 0; i < 50; i++) { var text = $"item {i} - "; for (int j = 0; j < 160; j++) { var col = j.ToString (); text += col.Length == 1 ? col [0] : col [1]; } source.Add (text); } var listView = new ListView (source) { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (listView); var newScrollBarView = new ScrollBarView (listView, false, false) { KeepContentAlwaysInViewport = true }; win.Add (newScrollBarView); newScrollBarView.ChangedPosition += () => { listView.LeftItem = newScrollBarView.Position; if (listView.LeftItem != newScrollBarView.Position) { newScrollBarView.Position = listView.LeftItem; } Assert.Equal (newScrollBarView.Position, listView.LeftItem); listView.SetNeedsDisplay (); }; listView.DrawContent += (e) => { newScrollBarView.Size = listView.Maxlength; Assert.Equal (newScrollBarView.Size, listView.Maxlength); newScrollBarView.Position = listView.LeftItem; Assert.Equal (newScrollBarView.Position, listView.LeftItem); newScrollBarView.Refresh (); }; top.Ready += () => { newScrollBarView.Position = 100; Assert.Equal (newScrollBarView.Position, newScrollBarView.Size - listView.LeftItem + (listView.LeftItem - listView.Bounds.Width)); Assert.Equal (newScrollBarView.Position, listView.LeftItem); Assert.Equal (92, newScrollBarView.Position); Assert.Equal (92, listView.LeftItem); Application.RequestStop (); }; top.Add (win); Application.Run (); Application.Shutdown (); }); Assert.Null (exception); } [Fact] [AutoInitShutdown] public void Internal_Tests () { var top = Application.Top; Assert.Equal (new Rect (0, 0, 80, 25), top.Bounds); var view = new View () { Width = Dim.Fill (), Height = Dim.Fill () }; top.Add (view); var sbv = new ScrollBarView (view, true); top.Add (sbv); Assert.Equal (view, sbv.Host); sbv.Size = 40; sbv.Position = 0; sbv.OtherScrollBarView.Size = 100; sbv.OtherScrollBarView.Position = 0; // Host bounds is empty. Assert.False (sbv.CanScroll (10, out int max, sbv.IsVertical)); Assert.Equal (0, max); Assert.False (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical)); Assert.Equal (0, max); // They aren't visible so they aren't drawn. Assert.False (sbv.Visible); Assert.False (sbv.OtherScrollBarView.Visible); top.LayoutSubviews (); // Now the host bounds is not empty. Assert.True (sbv.CanScroll (10, out max, sbv.IsVertical)); Assert.Equal (10, max); Assert.True (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical)); Assert.Equal (10, max); Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical)); Assert.Equal (40, sbv.Size); Assert.Equal (15, max); // 15+25=40 Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical)); Assert.Equal (100, sbv.OtherScrollBarView.Size); Assert.Equal (20, max); // 20+80=100 Assert.False (sbv.Visible); Assert.False (sbv.OtherScrollBarView.Visible); sbv.KeepContentAlwaysInViewport = false; sbv.OtherScrollBarView.KeepContentAlwaysInViewport = false; Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical)); Assert.Equal (39, max); Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical)); Assert.Equal (99, max); Assert.True (sbv.Visible); Assert.True (sbv.OtherScrollBarView.Visible); } [Fact, AutoInitShutdown] public void Hosting_ShowBothScrollIndicator_Invisible () { var textView = new TextView () { Width = Dim.Fill (), Height = Dim.Fill (), Text = "This is the help text for the Second Step.\n\nPress the button to see a message box.\n\nEnter name too." }; var win = new Window ("Test") { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (textView); var scrollBar = new ScrollBarView (textView, true); scrollBar.ChangedPosition += () => { textView.TopRow = scrollBar.Position; if (textView.TopRow != scrollBar.Position) { scrollBar.Position = textView.TopRow; } textView.SetNeedsDisplay (); }; scrollBar.OtherScrollBarView.ChangedPosition += () => { textView.LeftColumn = scrollBar.OtherScrollBarView.Position; if (textView.LeftColumn != scrollBar.OtherScrollBarView.Position) { scrollBar.OtherScrollBarView.Position = textView.LeftColumn; } textView.SetNeedsDisplay (); }; scrollBar.VisibleChanged += () => { if (scrollBar.Visible && textView.RightOffset == 0) { textView.RightOffset = 1; } else if (!scrollBar.Visible && textView.RightOffset == 1) { textView.RightOffset = 0; } }; scrollBar.OtherScrollBarView.VisibleChanged += () => { if (scrollBar.OtherScrollBarView.Visible && textView.BottomOffset == 0) { textView.BottomOffset = 1; } else if (!scrollBar.OtherScrollBarView.Visible && textView.BottomOffset == 1) { textView.BottomOffset = 0; } }; textView.DrawContent += (e) => { scrollBar.Size = textView.Lines; scrollBar.Position = textView.TopRow; if (scrollBar.OtherScrollBarView != null) { scrollBar.OtherScrollBarView.Size = textView.Maxlength; scrollBar.OtherScrollBarView.Position = textView.LeftColumn; } scrollBar.LayoutSubviews (); scrollBar.Refresh (); }; Application.Top.Add (win); Application.Begin (Application.Top); ((FakeDriver)Application.Driver).SetBufferSize (45, 20); Assert.True (scrollBar.AutoHideScrollBars); Assert.Equal (5, textView.Lines); Assert.Equal (42, textView.Maxlength); Assert.Equal (0, textView.LeftColumn); Assert.Equal (0, scrollBar.Position); Assert.Equal (0, scrollBar.OtherScrollBarView.Position); var expected = @" ┌ Test ─────────────────────────────────────┐ │This is the help text for the Second Step. │ │ │ │Press the button to see a message box. │ │ │ │Enter name too. │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └───────────────────────────────────────────┘ "; var pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); Assert.Equal (new Rect (0, 0, 45, 20), pos); textView.WordWrap = true; ((FakeDriver)Application.Driver).SetBufferSize (26, 20); Application.Refresh (); Assert.True (textView.WordWrap); Assert.True (scrollBar.AutoHideScrollBars); Assert.Equal (7, textView.Lines); Assert.Equal (22, textView.Maxlength); Assert.Equal (0, textView.LeftColumn); Assert.Equal (0, scrollBar.Position); Assert.Equal (0, scrollBar.OtherScrollBarView.Position); expected = @" ┌ Test ──────────────────┐ │This is the help text │ │for the Second Step. │ │ │ │Press the button to │ │see a message box. │ │ │ │Enter name too. │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────────────────────┘ "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); Assert.Equal (new Rect (0, 0, 26, 20), pos); ((FakeDriver)Application.Driver).SetBufferSize (10, 10); Application.Refresh (); Assert.True (textView.WordWrap); Assert.True (scrollBar.AutoHideScrollBars); Assert.Equal (20, textView.Lines); Assert.Equal (7, textView.Maxlength); Assert.Equal (0, textView.LeftColumn); Assert.Equal (0, scrollBar.Position); Assert.Equal (0, scrollBar.OtherScrollBarView.Position); expected = @" ┌ Test ──┐ │This ▲│ │is the ┬│ │help ││ │text ┴│ │for ░│ │the ░│ │Second ░│ │Step. ▼│ └────────┘ "; pos = GraphViewTests.AssertDriverContentsWithFrameAre (expected, output); Assert.Equal (new Rect (0, 0, 10, 10), pos); } [Fact, AutoInitShutdown] public void ContentBottomRightCorner_Not_Redraw_If_Both_Size_Equal_To_Zero () { var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; var label = new Label (text); Application.Top.Add (label); var sbv = new ScrollBarView (label, true, true) { Size = 100, }; sbv.OtherScrollBarView.Size = 100; Application.Begin (Application.Top); Assert.Equal (100, sbv.Size); Assert.Equal (100, sbv.OtherScrollBarView.Size); Assert.True (sbv.ShowScrollIndicator); Assert.True (sbv.OtherScrollBarView.ShowScrollIndicator); Assert.True (sbv.Visible); Assert.True (sbv.OtherScrollBarView.Visible); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a tes▲ This is a tes┬ This is a tes┴ This is a tes░ This is a tes▼ ◄├─┤░░░░░░░░► ", output); sbv.Size = 0; sbv.OtherScrollBarView.Size = 0; Assert.Equal (0, sbv.Size); Assert.Equal (0, sbv.OtherScrollBarView.Size); Assert.False (sbv.ShowScrollIndicator); Assert.False (sbv.OtherScrollBarView.ShowScrollIndicator); Assert.False (sbv.Visible); Assert.False (sbv.OtherScrollBarView.Visible); Application.Top.Redraw (Application.Top.Bounds); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a test This is a test This is a test This is a test This is a test This is a test ", output); sbv.Size = 50; sbv.OtherScrollBarView.Size = 50; Assert.Equal (50, sbv.Size); Assert.Equal (50, sbv.OtherScrollBarView.Size); Assert.True (sbv.ShowScrollIndicator); Assert.True (sbv.OtherScrollBarView.ShowScrollIndicator); Assert.True (sbv.Visible); Assert.True (sbv.OtherScrollBarView.Visible); Application.Top.Redraw (Application.Top.Bounds); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a tes▲ This is a tes┬ This is a tes┴ This is a tes░ This is a tes▼ ◄├──┤░░░░░░░► ", output); } [Fact, AutoInitShutdown] public void ContentBottomRightCorner_Not_Redraw_If_One_Size_Equal_To_Zero () { var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; var label = new Label (text); Application.Top.Add (label); var sbv = new ScrollBarView (label, true, false) { Size = 100, }; Application.Begin (Application.Top); Assert.Equal (100, sbv.Size); Assert.Null (sbv.OtherScrollBarView); Assert.True (sbv.ShowScrollIndicator); Assert.True (sbv.Visible); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a tes▲ This is a tes┬ This is a tes┴ This is a tes░ This is a tes░ This is a tes▼ ", output); sbv.Size = 0; Assert.Equal (0, sbv.Size); Assert.False (sbv.ShowScrollIndicator); Assert.False (sbv.Visible); Application.Top.Redraw (Application.Top.Bounds); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a test This is a test This is a test This is a test This is a test This is a test ", output); } [Fact, AutoInitShutdown] public void ShowScrollIndicator_False_Must_Also_Set_Visible_To_False_To_Not_Respond_To_Events () { var clicked = false; var text = "This is a test\nThis is a test\nThis is a test\nThis is a test\nThis is a test"; var label = new Label (text) { Width = 14, Height = 5 }; var btn = new Button (14, 0, "Click Me!"); btn.Clicked += () => clicked = true; Application.Top.Add (label, btn); var sbv = new ScrollBarView (label, true, false) { Size = 5, }; Application.Begin (Application.Top); Assert.Equal (5, sbv.Size); Assert.Null (sbv.OtherScrollBarView); Assert.False (sbv.ShowScrollIndicator); Assert.False (sbv.Visible); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a test[ Click Me! ] This is a test This is a test This is a test This is a test ", output); ReflectionTools.InvokePrivate ( typeof (Application), "ProcessMouseEvent", new MouseEvent () { X = 15, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.Null (Application.MouseGrabView); Assert.True (clicked); clicked = false; sbv.Visible = true; Assert.Equal (5, sbv.Size); Assert.False (sbv.ShowScrollIndicator); Assert.True (sbv.Visible); Application.Top.Redraw (Application.Top.Bounds); GraphViewTests.AssertDriverContentsWithFrameAre (@" This is a test[ Click Me! ] This is a test This is a test This is a test This is a test ", output); ReflectionTools.InvokePrivate ( typeof (Application), "ProcessMouseEvent", new MouseEvent () { X = 15, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.Null (Application.MouseGrabView); Assert.True (clicked); Assert.Equal (5, sbv.Size); Assert.False (sbv.ShowScrollIndicator); Assert.False (sbv.Visible); } } }