diff --git a/Terminal.Gui/Views/TableView.cs b/Terminal.Gui/Views/TableView.cs index 7040e51e2..f2c88bf60 100644 --- a/Terminal.Gui/Views/TableView.cs +++ b/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 { /// /// This property allows very wide tables to be rendered with horizontal scrolling 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)); } - /// /// Zero indexed offset for the to display in on line 2 of the control (first line being headers) /// /// This property allows very wide tables to be rendered with horizontal scrolling 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)); + /// + /// The index of in that the user has currently selected + /// + 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)); + } + + /// + /// The index of in that the user has currently selected + /// + public int SelectedRow { + get => selectedRow; + set => selectedRow = Math.Min (Table.Rows.Count - 1, Math.Max (0, value)); } /// @@ -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 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); + } + /// 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; } + + /// + /// Updates the viewport ( / ) to ensure that the users selected cell is visible and redraws control + /// + /// This always calls + public void RefreshViewport () + { + //TODO: implement + + Dictionary 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(); + } + /// /// Calculates which columns should be rendered given the in which to display and the ///