using InABox.Core; using NPOI.HSSF.Record; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; namespace InABox.DynamicGrid; public class CoreTableColumnSchema(CoreTable table) : IDynamicGridColumnSchema { private DynamicGridColumn[] _columns = table.Columns.Select(DynamicGridColumn.FromCoreColumn).NotNull().ToArray(); public IEnumerable ColumnNames => _columns.Select(x => x.ColumnName); public DynamicGridColumn GetColumn(string column) { return _columns.First(x => x.ColumnName == column); } public string? GetComment(string column) { return null; } public bool IsVisible(string column) { return true; } } public class CoreTableGrid : BaseDynamicGrid { public CoreTable Table { get; set; } = new(); public IDynamicGridColumnSchema? ColumnSchema { get; set; } #region Config protected override void Init() { } protected override void DoReconfigure(DynamicGridOptions options) { // We can add rows by default, but not edit them. options.EditRows = false; } #endregion #region Row Manipulation protected override void NewRow() { // This makes use of the fact that MasterData will be equivalent to Table (see 'ReloadData()'). var row = Table.NewRow(true); Table.Rows.Add(row); var dataRow = Data.NewRow(); dataRow.LoadValues(row.Values); Data.Rows.Add(dataRow); _recordmap[dataRow] = row; InvalidateGrid(); SelectedRows = [dataRow]; DoChanged(); } protected override bool EditRows(CoreRow[]? rows) { if(rows is null) { var row = Table.NewRow(true); Table.Rows.Add(row); var dataRow = Data.NewRow(); dataRow.LoadValues(row.Values); Data.Rows.Add(dataRow); _recordmap[dataRow] = row; InvalidateGrid(); SelectedRows = [dataRow]; DoChanged(); return true; } else { // It's not obvious how to edit a row, without this being overriden by a subclass. Hence, we have turned off editing, // and the case that 'rows' is null is just basically adding a new row. return false; } } public override void DeleteRows(params CoreRow[] rows) { foreach(var row in rows) { // This relies on MasterData being equivalent to Table. if(_recordmap.Remove(row, out var tableRow)) { Table.Rows.Remove(tableRow); } } } protected override void MoveRows(CoreRow[] rows, int index, bool isCopy = false) { CoreRow? targetRow; if(index < Data.Rows.Count) { var targetDataRow = Data.Rows[index]; targetRow = _recordmap.GetValueOrDefault(targetDataRow); } else { var lastDataRow = Data.Rows.LastOrDefault(); if(lastDataRow is null) { targetRow = null; } else if(!_recordmap.TryGetValue(lastDataRow, out var lastTargetRow)) { targetRow = null; } else if(lastTargetRow == Table.Rows.LastOrDefault()) { targetRow = null; } else { targetRow = Table.Rows[lastTargetRow.Index + 1]; } } if (isCopy) { rows = rows.ToArray(x => { var row = Table.NewRow(); row.LoadValues(x.Values); return row; }); } else { foreach(var row in rows) { if(_recordmap.TryGetValue(row, out var tableRow)) { Table.Rows.Remove(tableRow); } } } if(targetRow is not null) { var idx = Table.Rows.IndexOf(targetRow); Table.Rows.InsertRange(idx, rows); } else { Table.Rows.AddRange(rows); } Refresh(false, true); SelectedRows = rows.Select(row => { return _recordmap.FirstOrDefault(x => x.Value == row).Key; }).NotNull().ToArray(); } #endregion #region Columns private IDynamicGridColumnSchema GetColumnSchema() { return ColumnSchema ?? new CoreTableColumnSchema(Table); } protected override bool SelectColumns([NotNullWhen(true)] out DynamicGridColumns? columns) { var editor = new DynamicGridColumnsEditor(GetColumnSchema(), null) { WindowStartupLocation = WindowStartupLocation.CenterScreen }; editor.DirectEdit = IsDirectEditMode(); editor.Columns.AddRange(VisibleColumns); if (editor.ShowDialog().Equals(true)) { columns = editor.Columns; return true; } else { columns = null; return false; } } private DynamicGridColumns? _columns; protected override DynamicGridColumns LoadColumns() { return _columns ?? base.LoadColumns(); } public override DynamicGridColumns GenerateColumns() { var schema = GetColumnSchema(); var columns = new DynamicGridColumns(); columns.AddRange(schema.ColumnNames.Select(schema.GetColumn)); return columns; } protected override void SaveColumns(DynamicGridColumns columns) { _columns = columns; } #endregion #region Data protected override void ReloadData(CancellationToken token, Action action) { // I think this is all we need to do. If we were to do paging or something like that, this would fail, // since we would be adding the table to itself; but for now this will suffice. action(Table, null); } public override void OnItemSourceChanged(object value) { if(value is CoreTable table) { Table = table; Refresh(true, true); } } #endregion }