using System; using System.Collections; using System.Data; using System.Linq; 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; /// /// The data table this source wraps. /// public DataTable DataTable { get; private set; } private TableView _tableView; private Rect _lastBounds; private int _lastMaxCellWidth; private int _lastMinCellWidth; private ListColumnStyle _lastStyle; private IList _lastList; /// /// Creates a new columned list table instance based on the data in /// and dimensions from . /// /// /// /// public ListTableSource (IList list, TableView tableView, ListColumnStyle style) { this.List = list; this._tableView = tableView; Style = style; this.DataTable = CreateTable (CalculateColumns ()); // TODO: Determine the best event for this tableView.DrawContent += TableView_DrawContent; } /// public ListTableSource (IList list, TableView tableView) : this (list, tableView, new ListColumnStyle ()) { } private void TableView_DrawContent (object sender, DrawEventArgs e) { if ((!_tableView.Bounds.Equals (_lastBounds)) || _tableView.MaxCellWidth != _lastMaxCellWidth || _tableView.MinCellWidth != _lastMinCellWidth || Style != _lastStyle || this.List != _lastList) { this.DataTable = CreateTable (CalculateColumns ()); } _lastBounds = _tableView.Bounds; _lastMinCellWidth = _tableView.MaxCellWidth; _lastMaxCellWidth = _tableView.MaxCellWidth; _lastStyle = Style; _lastList = this.List; } /// 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 this.List [idx]; } } /// /// The number of items in the IList source /// public int Count => this.List.Count; /// public int Rows => this.DataTable.Rows.Count; /// public int Columns => this.DataTable.Columns.Count; /// public string [] ColumnNames => Enumerable.Range (0, Columns).Select (n => n.ToString ()).ToArray (); /// /// Creates a DataTable from an IList to display in a /// private DataTable CreateTable (int cols = 1) { var table = new DataTable (); for (int col = 0; col < cols; col++) { table.Columns.Add (new DataColumn (col.ToString ())); } for (int 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; } /// /// Returns the size in characters of the longest value read from /// /// private int CalculateMaxLength () { if (List == null || Count == 0) { return 0; } int maxLength = 0; foreach (var 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; } 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.Bounds.Height - _tableView.GetHeaderHeight (); cols = (int)Math.Ceiling (Count / f); } else { cols = ((int)Math.Ceiling (((float)_tableView.Bounds.Width - 1) / colWidth)) - 2; } return (cols > 1) ? cols : 1; } } }