Project panel: a panel too short for the scroll bar draws (#231)

The Project panel's vertical scroll bar clamped its thumb between 16
points and the track's height. When the track was shorter than 16
points (an empty project in a 1280 x 800 browser window at device pixel
ratio 2, or any short panel), that clamp panicked on the first frame:
the browser canvas went blank and the app stopped responding. The
thumb is now at most the track's length, and both scroll bars share
the calculation.

Test: a_short_project_panel_draws (ui_project_rows).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
bflatasticandClaude Opus 5.5 committed 2026-10-08 12:38:10 +07:00
1 parent 543bff29dc
commit 7612b220ef
2 files changed
+20 -2

No files matched your search

+8 -2
View File
@@ -174,6 +174,12 @@ fn fit(r: Rect, w: f32, h: f32) -> Rect {
Rect::from_center_size(r.center(), vec2(w * s, h * s))
}
/// A scroll bar thumb's length on a `track` long: the share of `content` in view, at least 16
/// points but never longer than the track (a panel only a few points tall still draws, #231).
fn thumb_len(track: f32, visible: f32, content: f32) -> f32 {
(track * visible / content).max(16.0).min(track).max(0.0)
}
/// An inline text edit in progress: (item, field `name`|`comment`, text).
type Editing = (u64, String, String);
fn edit_id() -> egui::Id {
@@ -340,7 +346,7 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
}
if overflow > 0.0 {
let track = Rect::from_min_max(pos2(opt_x0, list.max.y - 5.0), pos2(rect.max.x - 4.0, list.max.y - 1.0));
let tw = (track.width() * track.width() / (track.width() + overflow)).max(16.0);
let tw = thumb_len(track.width(), track.width(), track.width() + overflow);
let thumb = Rect::from_min_size(pos2(track.min.x + (track.width() - tw) * (hscroll / overflow), track.min.y), vec2(tw, track.height()));
let sresp = ui.interact(track.expand2(vec2(0.0, 2.0)), egui::Id::new("proj-hscroll"), Sense::drag());
p.rect_filled(track, 2.0, t.field_bg);
@@ -396,7 +402,7 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
let scroll = app.ui.project_scroll;
if max_scroll > 0.0 {
let track = Rect::from_min_max(pos2(rect.max.x - 6.0, list.min.y + 1.0), pos2(rect.max.x - 2.0, list.max.y - 7.0));
let th = (track.height() * list.height() / content_h).clamp(16.0, track.height());
let th = thumb_len(track.height(), list.height(), content_h);
let thumb = Rect::from_min_size(pos2(track.min.x, track.min.y + (track.height() - th) * (scroll / max_scroll)), vec2(track.width(), th));
let vresp = ui.interact(track.expand2(vec2(2.0, 0.0)), egui::Id::new("proj-vscroll"), Sense::drag());
p.rect_filled(thumb, 2.0, if vresp.hovered() || vresp.dragged() { t.text_dim } else { t.text_faint });
+12
View File
@@ -119,3 +119,15 @@ fn dragging_in_the_empty_area_box_selects_items() {
click_at(&mut h, from);
assert!(h.state().session.state.project_selection.is_empty());
}
/// A Project panel shorter than its scroll bar's thumb draws instead of panicking: an empty
/// project in a 1280 × 800 browser window at device pixel ratio 2 (640 × 400 points) left the
/// list too short for the thumb's 16-point minimum (#231).
#[test]
fn a_short_project_panel_draws() {
for height in [400.0, 300.0] {
let mut h = Harness::builder().with_size(egui::vec2(640.0, height)).build_eframe(|_| EffectcraftApp::new(Session::default()));
h.run_steps(3);
assert!(h.state().auto.find("project.empty").is_some(), "the Project panel drew at {height} points");
}
}