using System.Collections; using System.Data; namespace Terminal.Gui; /// /// implementation that wraps a . This class is /// mutable: changes are permitted to the wrapped . /// public class ListTableSource : ITableSource { /// The list this source wraps. public IList List; /// The style this source uses. public ListColumnStyle Style; private readonly TableView _tableView; private Rectangle _lastBounds; private IList _lastList; private int _lastMaxCellWidth; private int _lastMinCellWidth; private ListColumnStyle _lastStyle; /// /// Creates a new columned list table instance based on the data in and dimensions from /// . /// /// /// /// public ListTableSource (IList list, TableView tableView, ListColumnStyle style) { List = list; _tableView = tableView; Style = style; DataTable = CreateTable (CalculateColumns ()); // TODO: Determine the best event for this tableView.DrawingContent += TableView_DrawContent; } /// public ListTableSource (IList list, TableView tableView) : this (list, tableView, new ListColumnStyle ()) { } /// The number of items in the IList source public int Count => List.Count; /// The data table this source wraps. public DataTable DataTable { get; private set; } /// public object this [int row, int col] { get { int idx; if (Style.Orientation == Orientation.Vertical) { idx = col * Rows + row; } else { idx = row * Columns + col; } if (idx < 0 || idx >= Count) { return null; } return List [idx]; } } /// public int Rows => DataTable.Rows.Count; /// public int Columns => DataTable.Columns.Count; /// public string [] ColumnNames => Enumerable.Range (0, Columns).Select (n => n.ToString ()).ToArray (); private int CalculateColumns () { int cols; int colWidth = CalculateMaxLength (); if (colWidth > _tableView.MaxCellWidth) { colWidth = _tableView.MaxCellWidth; } if (_tableView.MinCellWidth > 0 && colWidth < _tableView.MinCellWidth) { if (_tableView.MinCellWidth > _tableView.MaxCellWidth) { colWidth = _tableView.MaxCellWidth; } else { colWidth = _tableView.MinCellWidth; } } if (Style.Orientation == Orientation.Vertical != Style.ScrollParallel) { float f = (float)_tableView.Viewport.Height - _tableView.GetHeaderHeight (); cols = (int)Math.Ceiling (Count / f); } else { cols = (int)Math.Ceiling (((float)_tableView.Viewport.Width - 1) / colWidth) - 2; } return cols > 1 ? cols : 1; } /// Returns the size in characters of the longest value read from /// private int CalculateMaxLength () { if (List is null || Count == 0) { return 0; } var maxLength = 0; foreach (object t in List) { int l; if (t is string s) { l = s.GetColumns (); } else { l = t.ToString ().Length; } if (l > maxLength) { maxLength = l; } } return maxLength; } /// Creates a DataTable from an IList to display in a private DataTable CreateTable (int cols = 1) { var table = new DataTable (); for (var col = 0; col < cols; col++) { table.Columns.Add (new DataColumn (col.ToString ())); } for (var row = 0; row < Count / table.Columns.Count; row++) { table.Rows.Add (); } // return partial row if (Count % table.Columns.Count != 0) { table.Rows.Add (); } return table; } private void TableView_DrawContent (object sender, DrawEventArgs e) { if (!_tableView.Viewport.Equals (_lastBounds) || _tableView.MaxCellWidth != _lastMaxCellWidth || _tableView.MinCellWidth != _lastMinCellWidth || Style != _lastStyle || List != _lastList) { DataTable = CreateTable (CalculateColumns ()); } _lastBounds = _tableView.Viewport; _lastMinCellWidth = _tableView.MaxCellWidth; _lastMaxCellWidth = _tableView.MaxCellWidth; _lastStyle = Style; _lastList = List; } }