M4: The radius field shows what a one-radius layer draws (#2222)

A boolean group, polygon, star or vector draws its first radius. Per-corner values a script or a
file left behind made its field read Mixed, and a relative edit started from the largest. The field
now shows radii[0] for those kinds, and a relative edit starts from it; rectangles and frames are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove and wrote
This commit is contained in:
Trevor BrownandClaude Opus 5.5 committed 2026-11-10 14:44:12 -05:00
1 parent bae366ba51
commit ec105d0f56
2 files changed
+21 -3

No files matched your search

+14
View File
@@ -1421,3 +1421,17 @@ fn a_boolean_group_has_one_corner_radius_field_and_a_mixed_selection_reads_mixed
type_into(&mut u, "Corner radius", "8", Key::Enter);
assert_eq!((radii(&u, g), radii(&u, r)), ([8.0; 4], [8.0; 4]));
}
/// A boolean group draws its first radius; per-corner values a script or a file left behind don't
/// make its field read Mixed, and a relative edit starts from the radius it draws.
#[test]
fn a_boolean_groups_field_shows_the_radius_it_draws() {
let (mut u, a, b) = setup();
let g = id(u.app.session.execute("bool.union", &json!({"ids": [a, b]})).unwrap());
let corners = json!({"topRightRadius": 30, "bottomRightRadius": 30, "bottomLeftRadius": 30});
u.app.session.execute("node.set", &json!({"ids": [g], "props": corners})).unwrap();
u.app.run("select.set", json!({"ids": [g]}));
assert_eq!(field(&mut u, "Corner radius").1, "0", "the radius it draws");
type_into(&mut u, "Corner radius", "+10", Key::Enter);
assert_eq!(u.app.session.doc().unwrap().node(g).unwrap().corners.radii, [10.0; 4], "0 + 10, not 30 + 10");
}
+7 -3
View File
@@ -57,7 +57,10 @@ pub(super) fn appearance(app: &mut FigApp, ui: &mut Ui, doc: &Document, sel: &[N
// For polygons, stars, boolean groups and closed vectors the same panel holds only the Corner
// smoothing row.
let smooth_ok = radius_ok && crate::selection_cache::every(doc, sel, |n| n.kind.has_corner_smoothing());
let r = common(doc, sel, |n| n.corners.uniform().map(|r| (r * 100.0).round() / 100.0));
// A layer with one radius (polygon, star, boolean group, vector) draws its first one, whatever
// the other three hold; a rectangle or frame shows a value only when its four corners agree.
let shown = |n: &Node| if n.kind.has_independent_corners() { n.corners.uniform() } else { n.corners.radii.first().copied() };
let r = common(doc, sel, |n| shown(n).map(|r| (r * 100.0).round() / 100.0));
widgets::sublabels(ui, tr("Opacity"), radius_ok.then_some(tr("Corner radius")));
row(ui, 32.0, |ui| {
let lead = Lead::Icon(Icon::Opacity, tr("Opacity"));
@@ -75,8 +78,9 @@ pub(super) fn appearance(app: &mut FigApp, ui: &mut Ui, doc: &Document, sel: &[N
"",
col,
);
// A layer with corners of its own starts from its largest.
let radius_of = |n: &Node| n.corners.uniform().unwrap_or_else(|| n.corners.radii.iter().copied().fold(0.0, f64::max));
// A relative edit starts from the radius shown; a rectangle with differing corners
// starts from its largest.
let radius_of = |n: &Node| shown(n).unwrap_or_else(|| n.corners.radii.iter().copied().fold(0.0, f64::max));
app.field_of(&ids, "cornerRadius", e, radius_of, |v| json!(v.max(0.0)));
let open = ui.data(|d| d.get_temp::<bool>(Id::unique("indep_corners"))).unwrap_or(false);
// Polygons, stars and boolean groups have no corners of their own: the button opens only