refactor: use data_col_to_visual via group_for helpers, add column group toggle

Add row_group_for/col_group_for to GridLayout, replacing inline
backward-search logic. Refactor grid renderer to use col_group_for
instead of pre-filtering col_items. Add gz keybinding for column
group collapse toggle, symmetric with z for rows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Edward Langley
2026-04-02 10:21:41 -07:00
parent 5136aadd86
commit edd6431444
4 changed files with 174 additions and 41 deletions

View File

@ -79,19 +79,10 @@ impl<'a> GridWidget<'a> {
})
.collect();
// Map each data-col index to its group name (None if ungrouped)
let col_groups: Vec<Option<String>> = {
let mut groups = Vec::new();
let mut current: Option<String> = None;
for entry in &layout.col_items {
match entry {
AxisEntry::GroupHeader { group_name, .. } => current = Some(group_name.clone()),
AxisEntry::DataItem(_) => groups.push(current.clone()),
}
}
groups
};
let has_col_groups = col_groups.iter().any(|g| g.is_some());
let has_col_groups = layout
.col_items
.iter()
.any(|e| matches!(e, AxisEntry::GroupHeader { .. }));
let available_cols = ((area.width.saturating_sub(ROW_HEADER_WIDTH)) / COL_WIDTH) as usize;
let visible_col_range =
@ -117,24 +108,35 @@ impl<'a> GridWidget<'a> {
Style::default(),
);
let mut x = area.x + ROW_HEADER_WIDTH;
let mut prev_group: Option<&str> = None;
let mut prev_group: Option<String> = None;
for ci in visible_col_range.clone() {
if x >= area.x + area.width {
break;
}
let group = col_groups[ci].as_deref();
let label = if group != prev_group {
group.unwrap_or("")
let col_group = layout.col_group_for(ci);
let group_name = col_group.as_ref().map(|(_, g)| g.clone());
let label = if group_name != prev_group {
match &col_group {
Some((cat, g)) => {
let indicator = if view.is_group_collapsed(cat, g) {
GROUP_COLLAPSED
} else {
GROUP_EXPANDED
};
format!("{indicator} {g}")
}
None => String::new(),
}
} else {
""
String::new()
};
prev_group = group;
prev_group = group_name;
buf.set_string(
x,
y,
format!(
"{:<width$}",
truncate(label, COL_WIDTH as usize),
truncate(&label, COL_WIDTH as usize),
width = COL_WIDTH as usize
),
group_style,