max / audiofiles
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+33 insertions,
-1 deletion
| @@ -29,10 +29,22 @@ | |||
| 29 | 29 | ) | |
| 30 | 30 | .on_hover_text("Search (press / to focus)"); | |
| 31 | 31 | ||
| 32 | + | // The field takes whatever the controls after it do not need. That width | |
| 33 | + | // cannot be known before they are drawn, so it is measured at the end of | |
| 34 | + | // the row and reused on the next frame: a one-frame correction nobody can | |
| 35 | + | // see, and it cannot drift the way the old fixed 160px budget did. That | |
| 36 | + | // budget predated the scope toggle, the result count, Save and the panel | |
| 37 | + | // toggles, so the row overflowed and clipped everything past Undo. | |
| 38 | + | // Theme-resolved spacing and per-platform font metrics rule out a constant. | |
| 39 | + | let trailing_id = ui.make_persistent_id("toolbar_trailing_width"); | |
| 40 | + | let trailing_w = ui | |
| 41 | + | .data(|d| d.get_temp::<f32>(trailing_id)) | |
| 42 | + | .unwrap_or(DEFAULT_TRAILING_WIDTH); | |
| 32 | 43 | let search_edit = egui::TextEdit::singleline(&mut state.search.search_query) | |
| 33 | 44 | .hint_text("Search samples... (/)") | |
| 34 | - | .desired_width(ui.available_width() - 160.0); | |
| 45 | + | .desired_width((ui.available_width() - trailing_w).max(MIN_SEARCH_WIDTH)); | |
| 35 | 46 | let resp = widgets::text_field(ui, search_edit); | |
| 47 | + | let trailing_start_x = ui.cursor().min.x; | |
| 36 | 48 | ||
| 37 | 49 | if state.focus_search { | |
| 38 | 50 | resp.request_focus(); | |
| @@ -171,9 +183,29 @@ | |||
| 171 | 183 | } else { | |
| 172 | 184 | draw_inline_panel_toggles(ui, state, detail_hidden); | |
| 173 | 185 | } | |
| 186 | + | ||
| 187 | + | // What the trailing controls actually consumed, for the next frame's field | |
| 188 | + | // width. The cursor keeps advancing even where painting was clipped, so | |
| 189 | + | // this reads true on the very frame the row overflows, which is what lets | |
| 190 | + | // one frame be enough to correct it. | |
| 191 | + | let measured = ui.cursor().min.x - trailing_start_x; | |
| 192 | + | if (measured - trailing_w).abs() > 0.5 { | |
| 193 | + | ui.data_mut(|d| d.insert_temp(trailing_id, measured)); | |
| 194 | + | ui.ctx().request_repaint(); | |
| 195 | + | } | |
| 174 | 196 | }); | |
| 175 | 197 | } | |
| 176 | 198 | ||
| 199 | + | /// Width assumed for the controls after the search field on the first frame, | |
| 200 | + | /// before the row has been measured once. Deliberately generous: too large only | |
| 201 | + | /// shortens the field for one frame, too small clips a control for one frame. | |
| 202 | + | const DEFAULT_TRAILING_WIDTH: f32 = 560.0; | |
| 203 | + | ||
| 204 | + | /// The search field never shrinks below this, however little room is left. Past | |
| 205 | + | /// that point the row is narrower than its own controls, which is the case the | |
| 206 | + | /// M-3 View-menu collapse below 900px exists to handle. | |
| 207 | + | const MIN_SEARCH_WIDTH: f32 = 120.0; | |
| 208 | + | ||
| 177 | 209 | /// Draw the full row of toolbar panel toggles (M-3 expanded layout). | |
| 178 | 210 | fn draw_inline_panel_toggles(ui: &mut egui::Ui, state: &mut BrowserState, detail_hidden: bool) { | |
| 179 | 211 | if widgets::toolbar_toggle( |