Browse Source

Merge branch 'main' of tig:migueldeicaza/gui.cs

Charlie Kindel 3 years ago
parent
commit
82eff23ea0

+ 59 - 0
Terminal.Gui/Views/TableView.cs

@@ -60,6 +60,9 @@ namespace Terminal.Gui {
 		private TableStyle style = new TableStyle ();
 		private Key cellActivationKey = Key.Enter;
 
+		Point? scrollLeftPoint;
+		Point? scrollRightPoint;
+
 		/// <summary>
 		/// The default maximum cell width for <see cref="TableView.MaxCellWidth"/> and <see cref="ColumnStyle.MaxWidth"/>
 		/// </summary>
@@ -261,6 +264,9 @@ namespace Terminal.Gui {
 				Move (0, 0);
 				var frame = Frame;
 
+				scrollRightPoint = null;
+				scrollLeftPoint = null;
+
 				// What columns to render at what X offset in viewport
 				var columnsToRender = CalculateViewport (bounds).ToArray ();
 
@@ -420,11 +426,25 @@ namespace Terminal.Gui {
 
 			for (int c = 0; c < availableWidth; c++) {
 
+				// Start by assuming we just draw a straight line the
+				// whole way but update to instead draw a header indicator
+				// or scroll arrow etc
 				var rune = Driver.HLine;
 
 				if (Style.ShowVerticalHeaderLines) {
 					if (c == 0) {
+						// for first character render line
 						rune = Style.ShowVerticalCellLines ? Driver.LeftTee : Driver.LLCorner;
+
+						// unless we have horizontally scrolled along
+						// in which case render an arrow, to indicate user
+						// can scroll left
+						if(Style.ShowHorizontalScrollIndicators && ColumnOffset > 0)
+						{
+							rune = Driver.LeftArrow;
+							scrollLeftPoint = new Point(c,row);
+						}
+							
 					}
 					// if the next column is the start of a header
 					else if (columnsToRender.Any (r => r.X == c + 1)) {
@@ -432,7 +452,20 @@ namespace Terminal.Gui {
 						/*TODO: is ┼ symbol in Driver?*/
 						rune = Style.ShowVerticalCellLines ? '┼' : Driver.BottomTee;
 					} else if (c == availableWidth - 1) {
+
+						// for the last character in the table
 						rune = Style.ShowVerticalCellLines ? Driver.RightTee : Driver.LRCorner;
+
+						// unless there is more of the table we could horizontally
+						// scroll along to see. In which case render an arrow,
+						// to indicate user can scroll right
+						if(Style.ShowHorizontalScrollIndicators &&
+							ColumnOffset + columnsToRender.Length < Table.Columns.Count)
+						{
+							rune = Driver.RightArrow;
+							scrollRightPoint = new Point(c,row);
+						}
+
 					}
 					  // if the next console column is the lastcolumns end
 					  else if (Style.ExpandLastColumn == false &&
@@ -898,6 +931,24 @@ namespace Terminal.Gui {
 
 			if (me.Flags.HasFlag (MouseFlags.Button1Clicked)) {
 
+				if (scrollLeftPoint != null 
+					&& scrollLeftPoint.Value.X == me.X
+					&& scrollLeftPoint.Value.Y == me.Y)
+				{
+					ColumnOffset--;
+					EnsureValidScrollOffsets ();
+					SetNeedsDisplay ();
+				}
+
+				if (scrollRightPoint != null 
+					&& scrollRightPoint.Value.X == me.X
+					&& scrollRightPoint.Value.Y == me.Y)
+				{
+					ColumnOffset++;
+					EnsureValidScrollOffsets ();
+					SetNeedsDisplay ();
+				}
+
 				var hit = ScreenToCell (me.X, me.Y);
 				if (hit != null) {
 
@@ -1369,6 +1420,14 @@ namespace Terminal.Gui {
 			/// </summary>
 			public bool ShowVerticalHeaderLines { get; set; } = true;
 
+			/// <summary>
+			/// True to render a arrows on the right/left of the table when 
+			/// there are more column(s) that can be scrolled to.  Requires
+			/// <see cref="ShowHorizontalHeaderUnderline"/> to be true.
+			/// Defaults to true
+			/// </summary>
+			public bool ShowHorizontalScrollIndicators { get; set; } = true;
+
 			/// <summary>
 			/// True to invert the colors of the first symbol of the selected cell in the <see cref="TableView"/>.
 			/// This gives the appearance of a cursor for when the <see cref="ConsoleDriver"/> doesn't otherwise show

+ 9 - 1
UICatalog/Scenarios/TableEditor.cs

@@ -20,6 +20,7 @@ namespace UICatalog.Scenarios {
 		private MenuItem miHeaderOverline;
 		private MenuItem miHeaderMidline;
 		private MenuItem miHeaderUnderline;
+		private MenuItem miShowHorizontalScrollIndicators;
 		private MenuItem miCellLines;
 		private MenuItem miFullRowSelect;
 		private MenuItem miExpandLastColumn;
@@ -55,7 +56,8 @@ namespace UICatalog.Scenarios {
 					miAlwaysShowHeaders = new MenuItem ("_AlwaysShowHeaders", "", () => ToggleAlwaysShowHeader()){Checked = tableView.Style.AlwaysShowHeaders, CheckType = MenuItemCheckStyle.Checked },
 					miHeaderOverline = new MenuItem ("_HeaderOverLine", "", () => ToggleOverline()){Checked = tableView.Style.ShowHorizontalHeaderOverline, CheckType = MenuItemCheckStyle.Checked },
 					miHeaderMidline = new MenuItem ("_HeaderMidLine", "", () => ToggleHeaderMidline()){Checked = tableView.Style.ShowVerticalHeaderLines, CheckType = MenuItemCheckStyle.Checked },
-					miHeaderUnderline =new MenuItem ("_HeaderUnderLine", "", () => ToggleUnderline()){Checked = tableView.Style.ShowHorizontalHeaderUnderline, CheckType = MenuItemCheckStyle.Checked },
+					miHeaderUnderline = new MenuItem ("_HeaderUnderLine", "", () => ToggleUnderline()){Checked = tableView.Style.ShowHorizontalHeaderUnderline, CheckType = MenuItemCheckStyle.Checked },
+					miShowHorizontalScrollIndicators = new MenuItem ("_HorizontalScrollIndicators", "", () => ToggleHorizontalScrollIndicators()){Checked = tableView.Style.ShowHorizontalScrollIndicators, CheckType = MenuItemCheckStyle.Checked },
 					miFullRowSelect =new MenuItem ("_FullRowSelect", "", () => ToggleFullRowSelect()){Checked = tableView.FullRowSelect, CheckType = MenuItemCheckStyle.Checked },
 					miCellLines =new MenuItem ("_CellLines", "", () => ToggleCellLines()){Checked = tableView.Style.ShowVerticalCellLines, CheckType = MenuItemCheckStyle.Checked },
 					miExpandLastColumn = new MenuItem ("_ExpandLastColumn", "", () => ToggleExpandLastColumn()){Checked = tableView.Style.ExpandLastColumn, CheckType = MenuItemCheckStyle.Checked },
@@ -205,6 +207,12 @@ namespace UICatalog.Scenarios {
 			tableView.Style.ShowHorizontalHeaderUnderline = miHeaderUnderline.Checked;
 			tableView.Update();
 		}
+		private void ToggleHorizontalScrollIndicators ()
+		{
+			miShowHorizontalScrollIndicators.Checked = !miShowHorizontalScrollIndicators.Checked;
+			tableView.Style.ShowHorizontalScrollIndicators = miShowHorizontalScrollIndicators.Checked;
+			tableView.Update();
+		}
 		private void ToggleFullRowSelect ()
 		{
 			miFullRowSelect.Checked = !miFullRowSelect.Checked;

+ 3 - 0
UICatalog/Scenarios/TreeUseCases.cs

@@ -75,6 +75,7 @@ namespace UICatalog.Scenarios {
 
 			if (currentTree != null) {
 				Win.Remove (currentTree);
+				currentTree.Dispose ();
 			}
 
 
@@ -148,6 +149,7 @@ namespace UICatalog.Scenarios {
 
 			if (currentTree != null) {
 				Win.Remove (currentTree);
+				currentTree.Dispose ();
 			}
 
 
@@ -180,6 +182,7 @@ namespace UICatalog.Scenarios {
 		{
 			if (currentTree != null) {
 				Win.Remove (currentTree);
+				currentTree.Dispose ();
 			}
 
 

+ 79 - 0
UnitTests/TableViewTests.cs

@@ -778,6 +778,85 @@ namespace Terminal.Gui.Views {
 			Application.Shutdown ();
 		}
 
+
+		[Fact]
+		public void ScrollIndicators ()
+		{
+			GraphViewTests.InitFakeDriver ();
+
+			var tableView = new TableView ();
+			tableView.ColorScheme = Colors.TopLevel;
+
+			// 3 columns are visibile
+			tableView.Bounds = new Rect (0, 0, 7, 5);
+			tableView.Style.ShowHorizontalHeaderUnderline = true;
+			tableView.Style.ShowHorizontalHeaderOverline = false;
+			tableView.Style.AlwaysShowHeaders = true;
+			tableView.Style.SmoothHorizontalScrolling = true;
+
+			var dt = new DataTable ();
+			dt.Columns.Add ("A");
+			dt.Columns.Add ("B");
+			dt.Columns.Add ("C");
+			dt.Columns.Add ("D");
+			dt.Columns.Add ("E");
+			dt.Columns.Add ("F");
+
+			dt.Rows.Add (1, 2, 3, 4, 5, 6);
+
+			tableView.Table = dt;
+
+			// select last visible column
+			tableView.SelectedColumn = 2; // column C
+
+			tableView.Redraw (tableView.Bounds);
+
+			// user can only scroll right so sees right indicator
+			// Because first column in table is A
+			string expected = 
+				@"
+│A│B│C│
+├─┼─┼─►
+│1│2│3│";
+
+			GraphViewTests.AssertDriverContentsAre (expected, output);
+
+
+			// Scroll right
+			tableView.ProcessKey (new KeyEvent () { Key = Key.CursorRight });
+
+
+			// since A is now pushed off screen we get indicator showing
+			// that user can scroll left to see first column
+			tableView.Redraw (tableView.Bounds);
+
+			expected =
+				@"
+│B│C│D│
+◄─┼─┼─►
+│2│3│4│";
+
+			GraphViewTests.AssertDriverContentsAre (expected, output);
+
+
+			// Scroll right twice more (to end of columns)
+			tableView.ProcessKey (new KeyEvent () { Key = Key.CursorRight });
+			tableView.ProcessKey (new KeyEvent () { Key = Key.CursorRight });
+
+			tableView.Redraw (tableView.Bounds);
+
+			expected =
+				@"
+│D│E│F│
+◄─┼─┼─┤
+│4│5│6│";
+
+			GraphViewTests.AssertDriverContentsAre (expected, output);
+
+			// Shutdown must be called to safely clean up Application if Init has been called
+			Application.Shutdown ();
+		}
+
 		/// <summary>
 		/// Builds a simple table of string columns with the requested number of columns and rows
 		/// </summary>