Added selected cell properties

This commit is contained in:
tznind
2020-11-19 13:50:23 +00:00
parent dcb020ab14
commit bfefc724df

View File

@@ -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>