Skip to main content

max / quasi

Ask a row its name once in the egui renderer Wave 1c. cells_name and row_name asked the same question of what is now the same type, and answered it two ways: one walked the row cell by cell, the other flattened every cell's content into a fresh Vec and walked that. The flattening one is gone. It cloned every node in the row to find the first string in it, once per row per frame, in a renderer whose standing promise is that the same description at the same width is the same picture. The cell-by- cell walk stops at the first cell that says anything. announce_row and tick_cell are left alone. They are nine and seven lines of table-specific work rather than copies of list_row, so the lane's own description was wrong about them and this records that rather than inventing a merge to satisfy it. The List and Table arms are also left alone, for the reason wave 1a reached in the webview: a list draws rows down a column and a table draws a grid, and that is the look rather than duplicated logic. Wave 0's two open questions here are answered. row_part applying the cell's room() to every text leaf is right: flow is how many lines the cell may take, and a token in the same cell is not a text leaf and is not capped by it. intrinsic_width returning None when any leaf cannot say is right rather than merely conservative: a sum containing an unknown is unknown. 148 tests green.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01P8ostB2UmZJGj5WjSHRSot
Author: Max Johnson <me@maxj.phd> · 2026-09-06 01:27 UTC
Signed with PGP, not checked
Commit: 9a773153bc7b2e8186f44929aa94709e1e2b3d34
Parent: d1f2a18
1 file changed, +13 insertions, -20 deletions
@@ -1660,27 +1660,13 @@
1660 1660 if index != 0 || (row.activate.is_none() && row.menu.is_empty()) {
1661 1661 return;
1662 1662 }
1663 - let named = cells_name(row);
1663 + let named = row_name(row);
1664 1664 response.widget_info(|| {
1665 1665 egui::WidgetInfo::labeled(egui::WidgetType::Button, ui.is_enabled(), &named)
1666 1666 });
1667 1667 }
1668 1668
1669 1669 /// What a table row is called: the first thing in its first cell.
1670 - ///
1671 - /// [`row_name`]'s counterpart for [`quasi_router::Cells`], which holds cells
1672 - /// rather than parts. Same rule and the same reason: it is where the row's name
1673 - /// already is.
1674 - fn cells_name(row: &quasi_router::Cells) -> String {
1675 - row.cells
1676 - .iter()
1677 - .find_map(|cell| {
1678 - let said = row_leaf_text(&cell.content);
1679 - (!said.is_empty()).then_some(said)
1680 - })
1681 - .unwrap_or_default()
1682 - }
1683 -
1684 1670 /// The first thing a run of leaves says.
1685 1671 fn row_leaf_text(parts: &[Node]) -> String {
1686 1672 parts
@@ -1699,13 +1685,20 @@
1699 1685 /// For [`egui::WidgetInfo`], which needs one string where a row is a run of
1700 1686 /// leaves. The first textual part is what `Row::new` takes and what a reader
1701 1687 /// would call the row, so there is nothing to invent here.
1688 + ///
1689 + /// One function since the 2026-09-05 collapse. `cells_name` was its counterpart
1690 + /// for the other container and asked the same question of the same type, cell
1691 + /// by cell rather than over a flattened copy. This keeps the cell-by-cell
1692 + /// walk: it is the one that does not clone every node in the row, and this
1693 + /// runs per frame.
1702 1694 fn row_name(row: &quasi_router::Row) -> String {
1703 - let parts: Vec<Node> = row
1704 - .cells
1695 + row.cells
1705 1696 .iter()
1706 - .flat_map(|cell| cell.content.iter().cloned())
1707 - .collect();
1708 - row_leaf_text(&parts)
1697 + .find_map(|cell| {
1698 + let said = row_leaf_text(&cell.content);
1699 + (!said.is_empty()).then_some(said)
1700 + })
1701 + .unwrap_or_default()
1709 1702 }
1710 1703
1711 1704 /// One part of a row's run.