2 Commits

Author SHA1 Message Date
landon a700eed63c Refresh Story Bible reference ranges when the header folds or unfolds
Folding/unfolding the header moves the frontmatter in or out of
`buffer`, shifting every char offset into it, but after_view_change()
never recomputed current_references — so the cached ranges stayed
pointing at pre-toggle positions and highlights landed on unrelated
words. Recompute them alongside the other view-state invalidations it
already does.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-03 15:32:17 -05:00
landon 80f3d50fc4 Stop the file tree from centering short folder/file names
ui.add_sized() centers a widget narrower than the box it's given, and
Button/SelectableLabel size themselves to their actual text — so a
short name in a wide column (a folder with no trailing badges, most
visibly) drifted away from its own indent, landing to the right of
its own deeper children. Pin main_align to the start so every name
sits right after its indent regardless of length.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-03 15:32:13 -05:00
2 changed files with 47 additions and 10 deletions
+42 -10
View File
@@ -415,13 +415,32 @@ impl App {
+ if show_tag { tag_w } else { 0.0 }; + if show_tag { tag_w } else { 0.0 };
let name_w = let name_w =
(row_width - indent - trailing).max(0.0); (row_width - indent - trailing).max(0.0);
// `add_sized` centers a widget
// smaller than the box it's given
// — fine for a fixed-width badge,
// but it let a short folder name
// drift away from the indent that
// was just drawn for it, and
// further than its own deeper
// children whose names fill more
// of their (narrower) box. Pinning
// `main_align` to the start keeps
// the name anchored right after
// the indent regardless of length.
let button_response = ui let button_response = ui
.add_sized( .allocate_ui_with_layout(
[name_w, 20.0], egui::vec2(name_w, 20.0),
egui::Button::new(text) egui::Layout::left_to_right(egui::Align::Center)
.frame(false) .with_main_align(egui::Align::Min),
.truncate(), |ui| {
ui.add(
egui::Button::new(text)
.frame(false)
.truncate(),
)
},
) )
.inner
.on_hover_text(&row.path); .on_hover_text(&row.path);
if button_response.clicked() { if button_response.clicked() {
@@ -563,16 +582,29 @@ impl App {
// file name simply spills out of the // file name simply spills out of the
// panel. The wrap mode is what it // panel. The wrap mode is what it
// actually reads. // actually reads.
//
// `add_sized` also *centers* a
// widget narrower than the box
// it's given, which drifted short
// file names away from the indent
// just like folder names did —
// `with_main_align(Min)` pins it
// to the start instead.
let mut label = ui let mut label = ui
.scope(|ui| { .scope(|ui| {
ui.style_mut().wrap_mode = ui.style_mut().wrap_mode =
Some(egui::TextWrapMode::Truncate); Some(egui::TextWrapMode::Truncate);
ui.add_sized( ui.allocate_ui_with_layout(
[label_w, 20.0], egui::vec2(label_w, 20.0),
egui::SelectableLabel::new( egui::Layout::left_to_right(egui::Align::Center)
selected, text, .with_main_align(egui::Align::Min),
), |ui| {
ui.add(egui::SelectableLabel::new(
selected, text,
))
},
) )
.inner
}) })
.inner; .inner;
if let Some(tooltip) = &tooltip { if let Some(tooltip) = &tooltip {
+5
View File
@@ -541,6 +541,11 @@ impl App {
self.spell_menu = None; self.spell_menu = None;
self.clear_lt(); self.clear_lt();
self.autocomplete = None; self.autocomplete = None;
// Story Bible reference ranges are char offsets into `buffer` too —
// stale ones (from before the header moved in or out) land on
// whatever text now happens to sit `header.len()` characters away
// from the real mention.
self.update_current_references();
} }
/// How many header fields are hidden right now, for the toggle's label. /// How many header fields are hidden right now, for the toggle's label.