feat(model): introduce virtual '_Measure' category for formulas

Refactor formula handling to use a virtual '_Measure' category.

- Formulas now default to targeting '_Measure' if no category is specified.
- '_Measure' items are dynamically computed from existing data items and
  formula targets, preventing redundant item storage.
- Updated persistence to handle '_Measure' formulas and items correctly in
  Markdown.
- Updated UI and model to use 'effective_item_names' for layout and item
  resolution.
- Updated tests to reflect the new '_Measure' behavior.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
This commit is contained in:
Edward Langley
2026-04-09 14:24:38 -07:00
parent 1690fc317b
commit c8b9d29690
3 changed files with 107 additions and 25 deletions

View File

@ -93,15 +93,7 @@ impl GridLayout {
let page_coords = page_cats
.iter()
.map(|cat| {
let items: Vec<String> = model
.category(cat)
.map(|c| {
c.ordered_item_names()
.into_iter()
.map(String::from)
.collect()
})
.unwrap_or_default();
let items: Vec<String> = model.effective_item_names(cat);
let sel = view
.page_selection(cat)
.map(String::from)
@ -518,11 +510,13 @@ fn expand_category(
let mut result = Vec::new();
let mut last_group: Option<&str> = None;
for item_name in cat.ordered_item_names() {
// Use effective_item_names so _Measure includes formula targets dynamically
let effective_names = model.effective_item_names(cat_name);
for item_name in &effective_names {
if view.is_hidden(cat_name, item_name) {
continue;
}
let item_group = cat.items.get(item_name).and_then(|i| i.group.as_deref());
let item_group = cat.items.get(item_name.as_str()).and_then(|i| i.group.as_deref());
// Emit a group header at each group boundary.
if item_group != last_group {