apply<T extends DataGridRow> method
Apply this event's transformation to the state. Returns the new state, or null if no state change should occur. Can return a Future for async operations.
Implementation
@override
Future<DataGridState<T>?> apply<T extends DataGridRow>(
EventContext<T> context,
) async {
final state = context.state;
final focused = state.selection.focusedCells;
if (focused.isEmpty) return null;
// Build a column-id → column map for fast lookup
final columnMap = <int, DataGridColumn<T>>{
for (final col in state.columns) col.id: col,
};
// Parse and sort cells: by row display-order index, then column index
final visibleColumns =
state.effectiveColumns.where((c) => c.visible).toList();
final colIndexMap = <int, int>{
for (int i = 0; i < visibleColumns.length; i++) visibleColumns[i].id: i,
};
final rowIndexMap = <double, int>{
for (int i = 0; i < state.displayOrder.length; i++)
state.displayOrder[i]: i,
};
final parsed = <({int rowIdx, int colIdx, double rowId, int colId})>[];
for (final cellId in focused) {
final (rowId, colId) = parseCellId(cellId);
final rowIdx = rowIndexMap[rowId];
final colIdx = colIndexMap[colId];
if (rowIdx == null || colIdx == null) continue;
parsed.add((rowIdx: rowIdx, colIdx: colIdx, rowId: rowId, colId: colId));
}
// Build (rowIdx, colIdx) → value map
final cellValues = <(int, int), String>{};
for (final cell in parsed) {
final row = state.rowsById[cell.rowId];
final col = columnMap[cell.colId];
final value = (row != null && col?.valueAccessor != null)
? col!.valueAccessor!(row)?.toString() ?? ''
: '';
cellValues[(cell.rowIdx, cell.colIdx)] = value;
}
// Collect unique sorted row and column indices
final rowIndices = parsed.map((c) => c.rowIdx).toSet().toList()..sort();
final colIndices = parsed.map((c) => c.colIdx).toSet().toList()..sort();
// Build CSV: for every selected row, output a value for every selected
// column index in order, using '' for gaps (cells not in the selection).
// Values are quoted when they contain a comma, double-quote, or newline.
String csvQuote(String value) {
if (value.contains(',') || value.contains('"') || value.contains('\n')) {
return '"${value.replaceAll('"', '""')}"';
}
return value;
}
final lines = rowIndices.map((rowIdx) {
return colIndices
.map((colIdx) => csvQuote(cellValues[(rowIdx, colIdx)] ?? ''))
.join(',');
});
final csv = lines.join('\n');
await Clipboard.setData(ClipboardData(text: csv));
return null;
}