Browse Source

Added selected cell properties

tznind 4 years ago
parent
commit
bfefc724df
1 changed files with 101 additions and 47 deletions
  1. 101 47
      Terminal.Gui/Views/TableView.cs

+ 101 - 47
Terminal.Gui/Views/TableView.cs

@@ -1,4 +1,5 @@
-using System;
+using NStack;
+using System;
 using System.Collections.Generic;
 using System.Data;
 using System.Linq;
@@ -12,6 +13,8 @@ namespace Terminal.Gui.Views {
 
 		private int columnOffset;
 		private int rowOffset;
+		private int selectedRow;
+		private int selectedColumn;
 
 		public DataTable Table { get; private set; }
 
@@ -20,42 +23,37 @@ namespace Terminal.Gui.Views {
 		/// </summary>
 		/// <remarks>This property allows very wide tables to be rendered with horizontal scrolling</remarks>
 		public int ColumnOffset {
-			get {
-				return columnOffset; 
-			}
+			get => columnOffset;
 
 			//try to prevent this being set to an out of bounds column
-			set {
-				//the value before we changed it
-				var origValue = columnOffset;
-
-				columnOffset = Math.Min (Table.Columns.Count - 1, Math.Max (0, value));
-				
-				//if value actually changed we must update UI
-				if(columnOffset != origValue)
-					SetNeedsDisplay();
-			}
+			set  => columnOffset = Math.Min (Table.Columns.Count - 1, Math.Max (0, value));
 		}
 
-
 		/// <summary>
 		/// Zero indexed offset for the <see cref="DataRow"/> to display in <see cref="Table"/> on line 2 of the control (first line being headers)
 		/// </summary>
 		/// <remarks>This property allows very wide tables to be rendered with horizontal scrolling</remarks>
 		public int RowOffset { 
-			get {
-				return rowOffset; 
-			}
-			set {
-				//the value before we changed it
-				var origValue = rowOffset;
+			get => rowOffset; 
+			set => rowOffset = Math.Min (Table.Rows.Count - 1, Math.Max (0, value));
+		}
 
-				rowOffset = Math.Min (Table.Rows.Count - 1, Math.Max (0, value));
+		/// <summary>
+		/// The index of <see cref="DataTable.Columns"/> in <see cref="Table"/> that the user has currently selected
+		/// </summary>
+		public int SelectedColumn {
+			get => selectedColumn;
 
-				//if value actually changed we must update UI
-				if(rowOffset != origValue)
-					SetNeedsDisplay();
-			}
+			//try to prevent this being set to an out of bounds column
+			set  => selectedColumn = Math.Min (Table.Columns.Count - 1, Math.Max (0, value));
+		}
+
+		/// <summary>
+		/// The index of <see cref="DataTable.Rows"/> in <see cref="Table"/> that the user has currently selected
+		/// </summary>
+		public int SelectedRow { 
+			get => selectedRow; 
+			set => selectedRow = Math.Min (Table.Rows.Count - 1, Math.Max (0, value));
 		}
 
 		/// <summary>
@@ -91,22 +89,19 @@ namespace Terminal.Gui.Views {
 
 			var frame = Frame;
 
-			int activeColor = ColorScheme.HotNormal;
-			int trackingColor = ColorScheme.HotFocus;
-
 			// What columns to render at what X offset in viewport
 			Dictionary<DataColumn, int> columnsToRender = CalculateViewport(bounds);
 
-			Driver.SetAttribute (ColorScheme.HotNormal);
+			Driver.SetAttribute (ColorScheme.Normal);
 
 			//invalidate current row (prevents scrolling around leaving old characters in the frame
 			Driver.AddStr(new string (' ',bounds.Width));
-
+			
 			// Render the headers
 			foreach(var kvp in columnsToRender) {
 				
 				Move (kvp.Value,0);
-				Driver.AddStr(kvp.Key.ColumnName+ SeparatorSymbol);
+				Driver.AddStr(Truncate(kvp.Key.ColumnName+ SeparatorSymbol,bounds.Width - kvp.Value));
 			}
 
 			//render the cells
@@ -114,6 +109,7 @@ namespace Terminal.Gui.Views {
 				
 				//invalidate current row (prevents scrolling around leaving old characters in the frame
 				Move (0,line);
+				Driver.SetAttribute(ColorScheme.Normal);
 				Driver.AddStr(new string (' ',bounds.Width));
 
 				//work out what Row to render
@@ -125,7 +121,14 @@ namespace Terminal.Gui.Views {
 
 				foreach(var kvp in columnsToRender) {
 					Move (kvp.Value,line);
-					Driver.AddStr(GetRenderedVal(Table.Rows[rowToRender][kvp.Key]) + SeparatorSymbol);
+
+					bool isSelectedCell = rowToRender == SelectedRow && kvp.Key.Ordinal == SelectedColumn;
+
+					Driver.SetAttribute(isSelectedCell? ColorScheme.HotFocus: ColorScheme.Normal);
+
+					
+					var valueToRender = GetRenderedVal(Table.Rows[rowToRender][kvp.Key]) + SeparatorSymbol;
+					Driver.AddStr(Truncate(valueToRender,bounds.Width - kvp.Value ));
 				}
 			}
 
@@ -138,50 +141,101 @@ namespace Terminal.Gui.Views {
 			}
 
 		}
-		
+
+		private ustring Truncate (string valueToRender, int availableHorizontalSpace)
+		{
+			if(string.IsNullOrEmpty(valueToRender) || valueToRender.Length < availableHorizontalSpace)
+				return valueToRender;
+
+			return valueToRender.Substring(0,availableHorizontalSpace);
+		}
+
 		/// <inheritdoc/>
 		public override bool ProcessKey (KeyEvent keyEvent)
 		{
 			switch (keyEvent.Key) {
 			case Key.CursorLeft:
-				ColumnOffset--;
+				SelectedColumn--;
+				RefreshViewport();
 				break;
 			case Key.CursorRight:
-				ColumnOffset++;
+				SelectedColumn++;
+				RefreshViewport();
 				break;
 			case Key.CursorDown:
-				RowOffset++;
+				SelectedRow++;
+				RefreshViewport();
 				break;
 			case Key.CursorUp:
-				RowOffset--;
+				SelectedRow--;
+				RefreshViewport();
 				break;
 			case Key.PageUp:
-				 RowOffset -= Frame.Height;
+				SelectedRow -= Frame.Height;
+				RefreshViewport();
 				break;
-			case Key.V | Key.CtrlMask:
 			case Key.PageDown:
-				 RowOffset += Frame.Height;
+				SelectedRow += Frame.Height;
+				RefreshViewport();
 				break;
 			case Key.Home | Key.CtrlMask:
-				RowOffset = 0;
-				ColumnOffset = 0;
+				SelectedRow = 0;
+				SelectedColumn = 0;
+				RefreshViewport();
 				break;
 			case Key.Home:
-				ColumnOffset = 0;
+				SelectedColumn = 0;
+				RefreshViewport();
 				break;
 			case Key.End | Key.CtrlMask:
 				//jump to end of table
-				RowOffset = Table.Rows.Count-1;
-				ColumnOffset = Table.Columns.Count-1;
+				SelectedRow = Table.Rows.Count-1;
+				SelectedColumn = Table.Columns.Count-1;
+				RefreshViewport();
 				break;
 			case Key.End:
 				//jump to end of row
-				ColumnOffset = Table.Columns.Count-1;				
+				SelectedColumn = Table.Columns.Count-1;
+				RefreshViewport();		
 				break;
 			}
 			PositionCursor ();
 			return true;
 		}
+
+		/// <summary>
+		/// Updates the viewport (<see cref="ColumnOffset"/> / <see cref="RowOffset"/>) to ensure that the users selected cell is visible and redraws control
+		/// </summary>
+		/// <remarks>This always calls <see cref="View.SetNeedsDisplay()"/></remarks>
+		public void RefreshViewport ()
+		{
+			//TODO: implement
+
+			Dictionary<DataColumn, int> columnsToRender = CalculateViewport(Bounds);
+
+
+			//if we have scrolled too far to the left 
+			if(SelectedColumn < columnsToRender.Keys.Min(col=>col.Ordinal)) {
+				ColumnOffset = SelectedColumn;
+			}
+
+			//if we have scrolled too far to the right
+			if(SelectedColumn > columnsToRender.Keys.Max(col=>col.Ordinal)) {
+				ColumnOffset = SelectedColumn;
+			}
+
+			//if we have scrolled too far down
+			if(SelectedRow > RowOffset + Bounds.Height-1) {
+				RowOffset = SelectedRow;
+			}
+			//if we have scrolled too far up
+			if(SelectedRow < RowOffset) {
+				RowOffset = SelectedRow;
+			}
+
+			SetNeedsDisplay();
+		}
+
 		/// <summary>
 		/// Calculates which columns should be rendered given the <paramref name="bounds"/> in which to display and the <see cref="ColumnOffset"/>
 		/// </summary>