Tool Sets: the Parametric category offers Fix, Symmetric, the dimensional constraints and Delete Constraints (part of #1134) (#1138)

This commit is contained in:
Marco Arnulfo
2026-10-19 02:29:54 -04:00
committed by GitHub
parent 9aea9b16c4
commit d4bacce885
3 changed files with 108 additions and 1 deletions
+33
View File
@@ -137,6 +137,11 @@ pub enum Icon {
Concentric,
Equal,
Fix,
Collinear,
Smooth,
Symmetric,
DelConstraint,
Parameters,
Measure,
Distance,
Area,
@@ -824,6 +829,34 @@ pub fn paint(p: &Painter, rect: Rect, icon: Icon, dim: bool) {
pen.fill_rect(7.0, 11.0, 10.0, 9.0, Color32::from_rgb(0xe6, 0xb4, 0x3c));
pen.arc(12.0, 11.0, 4.0, 0.0, 180.0, Color32::from_rgb(0xe6, 0xb4, 0x3c));
}
Collinear => {
pen.l(3.0, 19.0, 9.0, 15.0);
pen.la(12.0, 13.0, 21.0, 7.0);
}
Smooth => {
// A line running into an arc without a corner.
pen.l(3.0, 18.0, 11.0, 18.0);
pen.arc(11.0, 10.0, 8.0, -90.0, 0.0, a);
pen.dot(11.0, 18.0);
}
Symmetric => {
pen.poly(&[(9.0, 5.0), (4.0, 12.0), (9.0, 19.0)], false, b);
pen.poly(&[(15.0, 5.0), (20.0, 12.0), (15.0, 19.0)], false, b);
for y in [3.0, 9.0, 15.0] {
pen.la(12.0, y, 12.0, y + 4.0);
}
}
DelConstraint => {
let lock = alpha(Color32::from_rgb(0xe6, 0xb4, 0x3c));
pen.fill_rect(3.0, 12.0, 9.0, 8.0, lock);
pen.arc(7.5, 12.0, 3.5, 0.0, 180.0, lock);
pen.l(15.0, 13.0, 21.0, 19.0);
pen.l(21.0, 13.0, 15.0, 19.0);
}
Parameters => {
pen.rect(3.0, 4.0, 18.0, 16.0, b);
pen.text(12.0, 12.0, "fx", 10.0, a);
}
Coincident => {
pen.l(3.0, 20.0, 12.0, 12.0);
pen.l(12.0, 12.0, 21.0, 18.0);
+14 -1
View File
@@ -106,7 +106,11 @@ pub const DRAFTING: &[(&str, &[Tool], &[Tool])] = &[
("Table", &[(Icon::Table, "table", "Table")], &[]),
(
"Parametric",
&[(Icon::Constraint, "autoconstrain", "Auto Constrain")],
&[
(Icon::Constraint, "autoconstrain", "Auto Constrain"),
(Icon::DelConstraint, "delconstraint", "Delete Constraints"),
(Icon::Parameters, "parameters", "Parameters Manager"),
],
&[
(Icon::Coincident, "gccoincident", "Coincident"),
(Icon::Parallel, "gcparallel", "Parallel"),
@@ -116,6 +120,15 @@ pub const DRAFTING: &[(&str, &[Tool], &[Tool])] = &[
(Icon::Tangent, "gctangent", "Tangent"),
(Icon::Concentric, "gcconcentric", "Concentric"),
(Icon::Equal, "gcequal", "Equal"),
(Icon::Collinear, "gccollinear", "Collinear"),
(Icon::Smooth, "gcsmooth", "Smooth"),
(Icon::Symmetric, "gcsymmetric", "Symmetric"),
(Icon::Fix, "gcfix", "Fix"),
(Icon::DimLinear, "dclinear", "Linear"),
(Icon::DimAligned, "dcaligned", "Aligned"),
(Icon::DimAngular, "dcangular", "Angular"),
(Icon::DimRadius, "dcradius", "Radius"),
(Icon::DimDiameter, "dcdiameter", "Diameter"),
],
),
];
@@ -0,0 +1,61 @@
//! The Parametric category of the Tool Sets offers the constraint tools that only Tools ›
//! Parametric used to reach: Fix, Symmetric, Delete Constraints and the rest (#1134).
use cadcraft_engine::Session;
use cadcraft_ui_egui::{CadApp, Services};
use egui::accesskit::Role;
use egui::vec2;
use egui_kittest::Harness;
use egui_kittest::kittest::{NodeT, Queryable};
fn harness() -> Harness<'static, CadApp> {
let mut app = CadApp::new(Session::default(), Services::default());
app.ui.in_window_menu = false;
app.integrated_titlebar = true;
// Tall enough that the Parametric category, last in Drafting, is on screen.
let mut harness = Harness::builder().with_size(vec2(1280.0, 1600.0)).build_ui_state(
|ui, app: &mut CadApp| {
app.logic(&ui.ctx().clone());
app.ui(ui);
},
app,
);
harness.run_steps(5);
harness
}
#[test]
fn the_parametric_category_lists_fix_symmetric_and_delete_constraints() {
let parametric = cadcraft_ui_egui::palettes::DRAFTING.iter().find(|(name, _, _)| *name == "Parametric").unwrap();
let ids: Vec<&str> = parametric.1.iter().chain(parametric.2).map(|(_, cmd, _)| *cmd).collect();
for id in [
"gcfix",
"gcsymmetric",
"gccollinear",
"gcsmooth",
"dclinear",
"dcaligned",
"dcangular",
"dcradius",
"dcdiameter",
"delconstraint",
"parameters",
] {
assert!(ids.contains(&id), "{id} is missing from the Parametric tool set: {ids:?}");
}
let harness = harness();
for label in ["Fix", "Symmetric", "Delete Constraints"] {
let button = harness.get_by_role_and_label(Role::Button, label);
assert!(!button.accesskit_node().is_disabled(), "{label} is a known command, so its button is enabled");
}
}
#[test]
fn clicking_fix_in_the_tool_set_starts_gcfix() {
let mut harness = harness();
assert!(harness.state().session.running.is_none());
harness.get_by_role_and_label(Role::Button, "Fix").click();
harness.run_steps(5);
assert_eq!(harness.state().session.running.as_ref().map(|r| r.id.as_str()), Some("gcfix"));
}