diff --git a/crates/engine/src/cmd/arrange.rs b/crates/engine/src/cmd/arrange.rs index a043d987..903c1444 100644 --- a/crates/engine/src/cmd/arrange.rs +++ b/crates/engine/src/cmd/arrange.rs @@ -322,9 +322,9 @@ fn distribute(s: &mut Session, p: &Value) -> Result { let (start, end) = if to_slide { if horiz { (0.0, size.width) } else { (0.0, size.height) } } else { - let f = boxes.first().map(|b| b.1).unwrap_or_default(); - let l = boxes.last().map(|b| b.1).unwrap_or_default(); - if horiz { (f.x0, l.x1) } else { (f.y0, l.y1) } + let lo = |f: fn(&Rect) -> f64| boxes.iter().map(|b| f(&b.1)).fold(f64::INFINITY, f64::min); + let hi = |f: fn(&Rect) -> f64| boxes.iter().map(|b| f(&b.1)).fold(f64::NEG_INFINITY, f64::max); + if horiz { (lo(|r| r.x0), hi(|r| r.x1)) } else { (lo(|r| r.y0), hi(|r| r.y1)) } }; let n = boxes.len(); let gap = if n > 1 { ((end - start) - total) / (n - 1) as f64 } else { 0.0 }; diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 35b0ab39..8af46bcd 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -338,6 +338,19 @@ fn align_and_distribute() { assert!((x1 - 255.0).abs() < 1e-6, "{x1}"); } +#[test] +fn distribute_wide_middle_stays_in_selection_bounds() { + let mut s = session(); + let mut ids = vec![]; + for (x, w) in [(0.0, 10.0), (20.0, 100.0), (30.0, 10.0)] { + ids.push(s.execute("shape.insert", &json!({"preset": "rect", "rect": [x, 10, w, 10]})).unwrap()["id"].as_u64().unwrap()); + } + s.execute("edit.select", &json!({"ids": ids})).unwrap(); + s.execute("arrange.distribute", &json!({"dir": "horizontal", "to": "selection"})).unwrap(); + let xs: Vec = ids.iter().map(|i| s.execute("shape.inspect", &json!({"id": i})).unwrap()["box"]["x"].as_f64().unwrap()).collect(); + assert!(xs.iter().all(|x| (*x - [0.0, 10.0, 110.0][xs.iter().position(|y| y == x).unwrap()]).abs() < 1e-6), "{xs:?}"); +} + #[test] fn pointer_draw_move_resize() { let mut s = session();