groupRows method
Groups the displayed rows from start to end (inclusive, 0-based
indices into rows) into one Excel-outline-style group and returns it.
The group's first row stays visible as its header (it carries the +/−
toggle in the grid); collapsing hides the rows below it.
Returns null (no-op) when the range is invalid, spans fewer than two rows, or overlaps an existing group. Groups capture the row objects, so they survive sorting and filtering (the hidden set follows the rows).
Implementation
BCellRowGroup? groupRows(int start, int end) {
final displayRows = rows;
if (start < 0 || end >= displayRows.length || end <= start) return null;
final grouped = displayRows.sublist(start, end + 1);
for (final g in _rowGroups) {
for (final row in grouped) {
if (g.rows.contains(row)) return null; // overlap: reject
}
}
final group = BCellRowGroup._(grouped);
_rowGroups.add(group);
notifyListeners();
return group;
}