Design tab: translatable offer, one vocabulary, reports in the status line

- Offer table: user-facing strings carry the L() marker so xgettext
  extracts them; DesignOffer.hpp, DesignSketchTool.cpp and
  SketchInlineEditor.cpp are listed in localization/i18n/list.txt.
- Offer: model-mode Constrain sits in the same row as the sketch one;
  Interference is wired; Rib shows its R key; a verb that accepts the
  selection but is blocked by the document stays greyed with its reason
  instead of vanishing from the submenu; one refusal wording per verb.
- Extrude infers Join when the profile touches a solid (new
  CadDocument::body_touching_sketch) and on face push/pull; New body in
  free space. Revolve/Sweep/Loft/Boolean use the same result words.
- Interference and volume/area reports go to the status line in mm3/mm2
  instead of modal dialogs; Delete Body no longer asks (it is undoable).
- New feature names match the card header ("Extrude 3"), translated;
  "Coordinate system", "Angle (°)", center/color spelling, translated
  face and length readouts, slot hints say width.
- CAD gizmos in Prepare are selectable only with the CAD feature on; the
  sketch auto-close setting is stored per design.
- Docs: confirm/cancel rules, enabling the feature and MCP in
  design_tab.md; drift-only right-click in interaction-model.md; the
  portability note rewritten to describe the integration as it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QK4VgguuCAk2hZLWgcjJb9
This commit is contained in:
Claude
2026-09-30 08:34:25 +00:00
parent 829124982d
commit c74ddf8bb5
24 changed files with 662 additions and 582 deletions
+28 -1
View File
@@ -8657,12 +8657,13 @@ TEST_CASE("Hole standards: inch sizes by either name, with their 82° countersin
CHECK(doc.features[m].hole_cbore_diameter == 11.0);
}
TEST_CASE("Body colours and names survive a save and a load", "[CadDocument][recipe]")
TEST_CASE("Body colours, the modeling origin and the weld rule survive a save and a load", "[CadDocument][recipe]")
{
CadDocument doc;
const int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 10, 10, 0, "S");
doc.add_extrude(sk, 5, false, BooleanMode::New, "E");
doc.modeling_origin = Vec3d(110, 120, 0);
doc.auto_close_loops = false; // the design's weld rule travels with it
REQUIRE(doc.recompute());
doc.bodies[0].has_color = true;
doc.bodies[0].color = ColorRGBA(0.1f, 0.2f, 0.3f, 1.0f);
@@ -8675,6 +8676,9 @@ TEST_CASE("Body colours and names survive a save and a load", "[CadDocument][rec
CHECK(std::abs(back.bodies[0].color.g() - 0.2f) < 1e-6);
CHECK((back.modeling_origin - Vec3d(110, 120, 0)).norm() < 1e-9); // the project's own
CHECK(back.origin_from_recipe);
CHECK_FALSE(back.auto_close_loops);
back.auto_close_loops = true; // leave the kernel's global as the other tests expect it
back.recompute();
}
TEST_CASE("A new thread reads its radius as the nominal (major) radius", "[CadDocument][thread]")
@@ -8692,3 +8696,26 @@ TEST_CASE("A new thread reads its radius as the nominal (major) radius", "[CadDo
CHECK_FALSE(doc.recompute());
CHECK(doc.error.find("thread") != std::string::npos);
}
TEST_CASE("CadDocument: a profile on a body face touches it, one in free space does not", "[CadDocument]")
{
// The Extrude default reads this: a profile drawn on a body joins it (charter L6).
CadDocument doc;
const int base = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 20, 20, 10, "Base");
doc.add_extrude(base, 5.0, false, BooleanMode::New, "Block");
REQUIRE(doc.recompute());
REQUIRE(doc.bodies.size() == 1);
SketchPlane top = SketchPlane::XY();
top.origin = Vec3d(0, 0, 5); // the block's top face
const int on_face = doc.add_sketch(SketchShape::Rectangle, top, 6, 6, 3, "Boss");
SketchPlane above = SketchPlane::XY();
above.origin = Vec3d(0, 0, 30); // well clear of the block
const int in_air = doc.add_sketch(SketchShape::Rectangle, above, 6, 6, 3, "Floating");
REQUIRE(doc.recompute());
CHECK(doc.body_touching_sketch(on_face) == 0);
CHECK(doc.body_touching_sketch(in_air) == -1);
CHECK(doc.body_touching_sketch(-1) == -1);
CHECK(doc.body_touching_sketch(base + 1) == -1); // the extrude: not a sketch
}