Anchor Point(s): one point shows its frame's W and H, greyed

A single selected point has no size, so Transform's W and H read 0p0. InDesign
shows the object's width and height there, greyed out and not editable; with two
or more points they measure (and set) the points' bounds as before.

SelInfo keeps the selected objects' size from before the points replace the
bounds, and the anchor Transform section shows it in disabled W/H fields when
one point is selected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
moppeeerandClaude Opus 5.5 committed 2026-10-23 14:37:19 +02:00
1 parent db8b14eacc
commit 55606d2927
2 files changed
+34 -4

No files matched your search

+5
View File
@@ -34,6 +34,9 @@ use crate::theme::Tokens;
pub struct SelInfo {
/// Bounds measured from the rulers' zero point (as the X/Y fields show them).
pub page_rect: Rect,
/// Width and height of the selected objects themselves (with points selected, `page_rect`
/// measures the points).
pub object_size: (f64, f64),
pub count: usize,
pub fill: String,
pub stroke: String,
@@ -197,6 +200,7 @@ pub fn sel_info(app: &DesignApp) -> Option<SelInfo> {
};
b = Some(b.map_or(ib, |r| r.union(ib)));
}
let object_size = b.map_or((0.0, 0.0), |r| (r.width(), r.height()));
// Points selected with Direct Selection: Transform measures the points, not their paths.
let points = selected_anchor_points(app);
let b = match points.split_first() {
@@ -220,6 +224,7 @@ pub fn sel_info(app: &DesignApp) -> Option<SelInfo> {
};
Some(SelInfo {
page_rect: Rect::new(b.x0 - o.x, b.y0 - o.y, b.x1 - o.x, b.y1 - o.y),
object_size,
count: st.selection.items.len(),
fill: first.fill.swatch.clone(),
stroke: first.stroke.swatch.clone(),
+29 -4
View File
@@ -644,16 +644,19 @@ fn anchor_transform_section(app: &mut DesignApp, ui: &mut Ui, i: &SelInfo) {
app.ui.ref_point = p;
}
let mut set = serde_json::Map::new();
for (row, (lx, vx, kx, lw, vw, kw)) in
[("X:", x, "x", "W:", r.width(), "width"), ("Y:", y, "y", "H:", r.height(), "height")].into_iter().enumerate()
{
// A single point has no size: as InDesign, W and H show its object's, greyed out.
let single = super::selected_anchor_points(app).len() == 1;
let (w, h) = if single { i.object_size } else { (r.width(), r.height()) };
for (row, (lx, vx, kx, lw, vw, kw)) in [("X:", x, "x", "W:", w, "width"), ("Y:", y, "y", "H:", h, "height")].into_iter().enumerate() {
let yy = row as f32 * 25.0;
place(ui, sub(b, 40.0, yy, 18.0, FIELD_H), |ui| widgets::caption_w(ui, lx, 18.0));
if let Some(v) = place(ui, sub(b, 59.0, yy, 54.0, FIELD_H), |ui| measure(ui, &format!("pt_{kx}"), Some(vx), u, 54.0)) {
set.insert(kx.into(), json!(v));
}
place(ui, sub(b, 120.0, yy, 19.0, FIELD_H), |ui| widgets::caption_w(ui, lw, 19.0));
if let Some(v) = place(ui, sub(b, 140.0, yy, 54.0, FIELD_H), |ui| measure(ui, &format!("pt_{kw}"), Some(vw), u, 54.0)) {
let id = format!("pt_{kw}");
let field = NumField::measure(&id, Some(vw), u).width(54.0).enabled(!single);
if let Some(v) = place(ui, sub(b, 140.0, yy, 54.0, FIELD_H), |ui| field.show(ui)) {
set.insert(kw.into(), json!(v));
}
}
@@ -3609,6 +3612,28 @@ mod tests {
assert!((corner(&app, right).x - (pr.x + w)).abs() < 1e-9, "spread to twice the width");
}
/// One point has no size: W and H show its frame's, greyed out, as InDesign; two points
/// measure (and set) their own.
#[test]
fn one_selected_point_shows_its_frames_size_greyed() {
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
app.run("file.new", json!({})).unwrap();
let a = app.run("frame.create", json!({"rect": [72, 72, 172, 222]})).unwrap()["id"].as_u64().unwrap();
app.run("selection.set", json!({"anchors": [[a, 0, 0]]})).unwrap();
assert_eq!(super::super::sel_info(&app).unwrap().object_size, (100.0, 150.0));
let mut h = panel(app);
h.run_steps(2);
let greyed = |h: &Harness<'_, DesignApp>| {
h.query_all_by(|n| n.role() == egui::accesskit::Role::TextInput && n.is_disabled()).filter_map(|n| n.value()).collect::<Vec<_>>()
};
let u = units(h.state());
let f = |v| designcraft_geom::units::format_measure(v, u);
assert_eq!(greyed(&h), [f(100.0), f(150.0)], "the frame's W and H, greyed");
h.state_mut().run("selection.set", json!({"anchors": [[a, 0, 0], [a, 0, 2]]})).unwrap();
h.run_steps(2);
assert!(greyed(&h).is_empty(), "two points have a size of their own");
}
#[test]
fn transform_flips_and_rotates_from_properties() {
let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());