refactor(properties): entity property groups return Vec<PropSection>

Groundwork for making the Properties panel conform to the per-entity group/row
spec (PROPERTIES.md). The panel already renders a Vec of sections, but each
entity could only express a single geometry section.

Change PropertyEditable::geometry_properties (and the EntityTypeOps enum
dispatch) to return Vec<PropSection>, update the two impl macros, and flatten
in properties_sectioned so the panel shows [General] + the entity's groups.
Every entity builder is wrapped to return its existing section as a one-element
Vec — pure mechanical change, no rows or titles altered, panel output identical.

Enables Phase 2: rewriting each entity's groups/rows to match the spec.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-02 22:46:19 +03:00
1 parent 8164e14a19
commit b2b2bfb246
31 files changed
+147 -139

No files matched your search

+4 -4
View File
@@ -121,8 +121,8 @@ fn grips(arc: &Arc) -> Vec<GripDef> {
]
}
fn properties(arc: &Arc) -> PropSection {
PropSection {
fn properties(arc: &Arc) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Center X", "center_x", arc.center.x),
@@ -136,7 +136,7 @@ fn properties(arc: &Arc) -> PropSection {
),
edit("End Angle (deg)", "end_angle", arc.end_angle.to_degrees()),
],
}
}]
}
fn apply_geom_prop(arc: &mut Arc, field: &str, value: &str) {
@@ -313,7 +313,7 @@ impl crate::entities::traits::Grippable for Arc {
}
impl crate::entities::traits::PropertyEditable for Arc {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+6 -6
View File
@@ -384,7 +384,7 @@ impl Grippable for AttributeDefinition {
}
impl PropertyEditable for AttributeDefinition {
fn geometry_properties(&self, text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
let mut props = vec![
ro("Tag", "att_tag", self.tag.clone()),
ro("Prompt", "att_prompt", self.prompt.clone()),
@@ -478,10 +478,10 @@ impl PropertyEditable for AttributeDefinition {
p.value = PropValue::ReadOnly(self.default_value.clone());
}
}
PropSection {
vec![PropSection {
title: "Geometry".into(),
props,
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -625,8 +625,8 @@ impl Grippable for AttributeEntity {
}
impl PropertyEditable for AttributeEntity {
fn geometry_properties(&self, text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Tag", "atte_tag", self.tag.clone()),
@@ -720,7 +720,7 @@ impl PropertyEditable for AttributeEntity {
bool_yn(self.flags.annotative),
),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+3 -3
View File
@@ -118,8 +118,8 @@ fn grips(circle: &Circle) -> Vec<GripDef> {
]
}
fn properties(circle: &Circle) -> PropSection {
PropSection {
fn properties(circle: &Circle) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Center X", "center_x", circle.center.x),
@@ -137,7 +137,7 @@ fn properties(circle: &Circle) -> PropSection {
format!("{:.4}", circle.radius * 2.0 * std::f64::consts::PI),
),
],
}
}]
}
fn apply_geom_prop(circle: &mut Circle, field: &str, value: &str) {
+4 -4
View File
@@ -57,7 +57,7 @@ fn base_props(base: &DimensionBase) -> Vec<crate::scene::model::object::Property
]
}
fn properties(dim: &Dimension) -> PropSection {
fn properties(dim: &Dimension) -> Vec<PropSection> {
let mut props = base_props(dim.base());
match dim {
Dimension::Aligned(d) => {
@@ -129,10 +129,10 @@ fn properties(dim: &Dimension) -> PropSection {
));
}
}
PropSection {
vec![PropSection {
title: "Geometry".into(),
props,
}
}]
}
fn linear_like_props(
@@ -579,7 +579,7 @@ fn mirror_point(p: &mut acadrust::types::Vector3, p1: DVec3, p2: DVec3) {
}
impl PropertyEditable for Dimension {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
+3 -3
View File
@@ -158,12 +158,12 @@ fn grips(ell: &Ellipse) -> Vec<GripDef> {
]
}
fn properties(ell: &Ellipse) -> PropSection {
fn properties(ell: &Ellipse) -> Vec<PropSection> {
let r_major = (ell.major_axis.x * ell.major_axis.x
+ ell.major_axis.y * ell.major_axis.y
+ ell.major_axis.z * ell.major_axis.z)
.sqrt();
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Center X", "center_x", ell.center.x),
@@ -181,7 +181,7 @@ fn properties(ell: &Ellipse) -> PropSection {
format!("{:.4}", ell.minor_axis_ratio),
),
],
}
}]
}
fn apply_geom_prop(_ell: &mut Ellipse, _field: &str, _value: &str) {}
+4 -4
View File
@@ -8,7 +8,7 @@ use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Pr
use crate::scene::convert::tess_util::{arc_segments, arc_signed_span, wire_chord_tol, FallbackGeometry};
use crate::scene::model::wire_model::SnapHint;
fn properties(h: &Hatch) -> PropSection {
fn properties(h: &Hatch) -> Vec<PropSection> {
let pattern_type = match h.pattern_type {
acadrust::entities::HatchPatternType::Predefined => "Predefined",
acadrust::entities::HatchPatternType::UserDefined => "User Defined",
@@ -39,7 +39,7 @@ fn properties(h: &Hatch) -> PropSection {
.sum::<usize>()
})
.sum();
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Fill Type", "fill_type", fill_type),
@@ -73,7 +73,7 @@ fn properties(h: &Hatch) -> PropSection {
format!("{:.3}, {:.3}, {:.3}", h.normal.x, h.normal.y, h.normal.z),
),
],
}
}]
}
fn apply_geom_prop(h: &mut Hatch, field: &str, value: &str) {
@@ -103,7 +103,7 @@ fn apply_transform(h: &mut Hatch, t: &EntityTransform) {
}
impl PropertyEditable for Hatch {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
+3 -3
View File
@@ -19,8 +19,8 @@ fn grips(ins: &Insert) -> Vec<GripDef> {
vec![square_grip(0, glam::DVec3::new(w.x, w.y, w.z))]
}
fn properties(ins: &Insert) -> PropSection {
PropSection {
fn properties(ins: &Insert) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Insert X", "ins_x", ins.insert_point.x),
@@ -32,7 +32,7 @@ fn properties(ins: &Insert) -> PropSection {
edit("Rotation", "rotation", ins.rotation.to_degrees()),
ro("Block", "block", ins.block_name.clone()),
],
}
}]
}
fn apply_geom_prop(ins: &mut Insert, field: &str, value: &str) {
+4 -4
View File
@@ -191,7 +191,7 @@ fn hookline_dir_str(hd: &HooklineDirection) -> &'static str {
}
}
fn properties(leader: &Leader) -> PropSection {
fn properties(leader: &Leader) -> Vec<PropSection> {
let n = leader.vertices.len();
let mut props = vec![
// Style
@@ -283,10 +283,10 @@ fn properties(leader: &Leader) -> PropSection {
}
}
PropSection {
vec![PropSection {
title: "Geometry".into(),
props,
}
}]
}
fn apply_geom_prop(leader: &mut Leader, field: &str, value: &str) {
@@ -540,7 +540,7 @@ impl crate::entities::traits::Grippable for Leader {
}
impl crate::entities::traits::PropertyEditable for Leader {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+4 -4
View File
@@ -72,8 +72,8 @@ fn grips(line: &Line) -> Vec<GripDef> {
vec![square_grip(0, s), square_grip(1, e), center_grip(2, m)]
}
fn properties(line: &Line) -> PropSection {
PropSection {
fn properties(line: &Line) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Start X", "start_x", line.start.x),
@@ -84,7 +84,7 @@ fn properties(line: &Line) -> PropSection {
edit("End Z", "end_z", line.end.z),
ro("Length", "length", format!("{:.4}", line.length())),
],
}
}]
}
fn apply_geom_prop(line: &mut Line, field: &str, value: &str) {
@@ -232,7 +232,7 @@ impl crate::entities::traits::Grippable for Line {
}
impl crate::entities::traits::PropertyEditable for Line {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+4 -4
View File
@@ -322,9 +322,9 @@ fn grips(pline: &LwPolyline) -> Vec<GripDef> {
out
}
fn properties(pline: &LwPolyline) -> PropSection {
fn properties(pline: &LwPolyline) -> Vec<PropSection> {
let (length, area) = length_and_area(pline);
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Vertices", "vertices", pline.vertices.len().to_string()),
@@ -337,7 +337,7 @@ fn properties(pline: &LwPolyline) -> PropSection {
ro("Length", "length", format!("{length:.4}")),
ro("Area", "area", format!("{area:.4}")),
],
}
}]
}
/// Path length and enclosed area of a polyline, accounting for arc
@@ -587,7 +587,7 @@ impl crate::entities::traits::PropertyEditable for LwPolyline {
fn geometry_properties(
&self,
_text_style_names: &[String],
) -> crate::scene::model::object::PropSection {
) -> Vec<crate::scene::model::object::PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+12 -12
View File
@@ -115,9 +115,9 @@ impl Grippable for Face3D {
}
impl PropertyEditable for Face3D {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
use crate::entities::common::edit_prop as edit;
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("P1 X", "f3_p1x", self.first_corner.x),
@@ -133,7 +133,7 @@ impl PropertyEditable for Face3D {
edit("P4 Y", "f3_p4y", self.fourth_corner.y),
edit("P4 Z", "f3_p4z", self.fourth_corner.z),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -276,14 +276,14 @@ impl Grippable for PolygonMesh {
}
impl PropertyEditable for PolygonMesh {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let smooth = match self.smooth_type {
acadrust::entities::polygon_mesh::SurfaceSmoothType::NoSmooth => "None",
acadrust::entities::polygon_mesh::SurfaceSmoothType::Quadratic => "Quadratic",
acadrust::entities::polygon_mesh::SurfaceSmoothType::Cubic => "Cubic",
acadrust::entities::polygon_mesh::SurfaceSmoothType::Bezier => "Bezier",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("M count", "pm_m", self.m_vertex_count.to_string()),
@@ -314,7 +314,7 @@ impl PropertyEditable for PolygonMesh {
),
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
@@ -424,14 +424,14 @@ impl Grippable for PolyfaceMesh {
}
impl PropertyEditable for PolyfaceMesh {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let smooth = match self.smooth_surface {
acadrust::entities::PolyfaceSmoothType::None => "None",
acadrust::entities::PolyfaceSmoothType::Quadratic => "Quadratic",
acadrust::entities::PolyfaceSmoothType::Cubic => "Cubic",
acadrust::entities::PolyfaceSmoothType::Bezier => "Bezier",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Vertices", "pfm_v", self.vertices.len().to_string()),
@@ -464,7 +464,7 @@ impl PropertyEditable for PolyfaceMesh {
format!("{:.4}", self.thickness),
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
@@ -597,9 +597,9 @@ impl Grippable for Mesh {
}
impl PropertyEditable for Mesh {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let creased_edges = self.edges.iter().filter(|e| e.has_crease()).count();
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Vertices", "msh_v", self.vertices.len().to_string()),
@@ -618,7 +618,7 @@ impl PropertyEditable for Mesh {
if self.blend_crease { "Yes" } else { "No" },
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
+3 -3
View File
@@ -188,13 +188,13 @@ impl Grippable for MLine {
}
impl PropertyEditable for MLine {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let just_str = match self.justification {
acadrust::entities::MLineJustification::Top => "Top",
acadrust::entities::MLineJustification::Zero => "Zero",
acadrust::entities::MLineJustification::Bottom => "Bottom",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Style", "ml_style", self.style_name.clone()),
@@ -233,7 +233,7 @@ impl PropertyEditable for MLine {
},
},
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+4 -4
View File
@@ -192,8 +192,8 @@ fn grips(t: &MText) -> Vec<GripDef> {
vec![square_grip(0, p), triangle_grip(1, width_grip)]
}
fn properties(t: &MText, text_style_names: &[String]) -> PropSection {
PropSection {
fn properties(t: &MText, text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Insert X", "ins_x", t.insertion_point.x),
@@ -254,7 +254,7 @@ fn properties(t: &MText, text_style_names: &[String]) -> PropSection {
},
},
],
}
}]
}
fn apply_geom_prop(t: &mut MText, field: &str, value: &str) {
@@ -413,7 +413,7 @@ impl Grippable for MText {
}
impl PropertyEditable for MText {
fn geometry_properties(&self, text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
properties(self, text_style_names)
}
+4 -4
View File
@@ -520,7 +520,7 @@ fn choice(label: &str, field: &'static str, selected: &str, opts: &[&str]) -> Pr
}
}
fn properties(ml: &MultiLeader) -> PropSection {
fn properties(ml: &MultiLeader) -> Vec<PropSection> {
let ctx = &ml.context;
let total_pts: usize = ctx
.leader_roots
@@ -714,10 +714,10 @@ fn properties(ml: &MultiLeader) -> PropSection {
props.push(edit("Root Conn Z", "conn_z", root.connection_point.z));
}
PropSection {
vec![PropSection {
title: "Geometry".into(),
props,
}
}]
}
fn apply_geom_prop(ml: &mut MultiLeader, field: &str, value: &str) {
@@ -1047,7 +1047,7 @@ impl crate::entities::traits::Grippable for MultiLeader {
}
impl crate::entities::traits::PropertyEditable for MultiLeader {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+3 -3
View File
@@ -73,13 +73,13 @@ fn grips(ole: &Ole2Frame) -> Vec<GripDef> {
]
}
fn properties(ole: &Ole2Frame) -> PropSection {
fn properties(ole: &Ole2Frame) -> Vec<PropSection> {
let type_str = match ole.ole_object_type {
OleObjectType::Link => "Link",
OleObjectType::Embedded => "Embedded",
OleObjectType::Static => "Static",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Type", "ole_type", type_str),
@@ -114,7 +114,7 @@ fn properties(ole: &Ole2Frame) -> PropSection {
if ole.is_paper_space { "Yes" } else { "No" },
),
],
}
}]
}
fn apply_geom_prop(ole: &mut Ole2Frame, field: &str, value: &str) {
+3 -3
View File
@@ -178,15 +178,15 @@ fn grips(pt: &Point) -> Vec<GripDef> {
vec![square_grip(0, p)]
}
fn properties(pt: &Point) -> PropSection {
PropSection {
fn properties(pt: &Point) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("X", "loc_x", pt.location.x),
edit("Y", "loc_y", pt.location.y),
edit("Z", "loc_z", pt.location.z),
],
}
}]
}
fn apply_geom_prop(pt: &mut Point, field: &str, value: &str) {
+9 -9
View File
@@ -117,8 +117,8 @@ impl Grippable for Polyline {
}
impl PropertyEditable for Polyline {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Vertices", "vertices", self.vertices.len().to_string()),
@@ -131,7 +131,7 @@ impl PropertyEditable for Polyline {
},
},
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -386,14 +386,14 @@ impl Grippable for Polyline2D {
}
impl PropertyEditable for Polyline2D {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let smooth = match self.smooth_surface {
acadrust::entities::SmoothSurfaceType::None => "None",
acadrust::entities::SmoothSurfaceType::QuadraticBSpline => "Quadratic",
acadrust::entities::SmoothSurfaceType::CubicBSpline => "Cubic",
acadrust::entities::SmoothSurfaceType::Bezier => "Bezier",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Vertices", "vertices", self.vertices.len().to_string()),
@@ -419,7 +419,7 @@ impl PropertyEditable for Polyline2D {
},
},
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -604,7 +604,7 @@ impl Grippable for Polyline3D {
}
impl PropertyEditable for Polyline3D {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
use acadrust::entities::polyline3d::SmoothSurfaceType as SST;
let smooth = match self.smooth_type {
SST::None => "None",
@@ -612,7 +612,7 @@ impl PropertyEditable for Polyline3D {
SST::CubicBSpline => "Cubic",
SST::Bezier => "Bezier",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Vertices", "vertices", self.vertices.len().to_string()),
@@ -640,7 +640,7 @@ impl PropertyEditable for Polyline3D {
},
},
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+6 -6
View File
@@ -162,8 +162,8 @@ impl Grippable for RasterImage {
}
impl PropertyEditable for RasterImage {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("File", "ri_file", self.file_path.clone()),
@@ -203,7 +203,7 @@ impl PropertyEditable for RasterImage {
},
),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -423,8 +423,8 @@ impl Grippable for Wipeout {
}
impl PropertyEditable for Wipeout {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Insert X", "wo_ox", self.insertion_point.x),
@@ -464,7 +464,7 @@ impl PropertyEditable for Wipeout {
},
),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+6 -6
View File
@@ -88,8 +88,8 @@ impl Grippable for Ray {
}
impl PropertyEditable for Ray {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Base X", "ray_bx", self.base_point.x),
@@ -99,7 +99,7 @@ impl PropertyEditable for Ray {
edit("Dir Y", "ray_dy", self.direction.y),
edit("Dir Z", "ray_dz", self.direction.z),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -225,8 +225,8 @@ impl Grippable for XLine {
}
impl PropertyEditable for XLine {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Base X", "xl_bx", self.base_point.x),
@@ -236,7 +236,7 @@ impl PropertyEditable for XLine {
edit("Dir Y", "xl_dy", self.direction.y),
edit("Dir Z", "xl_dz", self.direction.z),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+3 -3
View File
@@ -118,12 +118,12 @@ impl Grippable for Shape {
// ── PropertyEditable ──────────────────────────────────────────────────────────
impl PropertyEditable for Shape {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let style_handle_display = match self.style_handle {
Some(h) if !h.is_null() => format!("{:X}", h.value()),
_ => "(none)".to_string(),
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Name", "shp_name", self.shape_name.clone()),
@@ -142,7 +142,7 @@ impl PropertyEditable for Shape {
edit("Normal Y", "shp_ny", self.normal.y),
edit("Normal Z", "shp_nz", self.normal.z),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+3 -3
View File
@@ -97,8 +97,8 @@ impl Grippable for Solid {
}
impl PropertyEditable for Solid {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("P1 X", "sl_p1x", self.first_corner.x),
@@ -115,7 +115,7 @@ impl PropertyEditable for Solid {
edit("P4 Z", "sl_p4z", self.fourth_corner.z),
edit("Thickness", "sl_thick", self.thickness),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+9 -9
View File
@@ -84,14 +84,14 @@ impl Grippable for Solid3D {
}
impl PropertyEditable for Solid3D {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let size = acis_size_str(
self.acis_data.has_data(),
self.acis_data.sat_data.len(),
self.acis_data.sab_data.len(),
self.acis_data.is_binary,
);
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro(
@@ -133,7 +133,7 @@ impl PropertyEditable for Solid3D {
},
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
@@ -160,14 +160,14 @@ impl Grippable for Region {
}
impl PropertyEditable for Region {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let size = acis_size_str(
self.acis_data.has_data(),
self.acis_data.sat_data.len(),
self.acis_data.sab_data.len(),
self.acis_data.is_binary,
);
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro(
@@ -201,7 +201,7 @@ impl PropertyEditable for Region {
self.silhouettes.len().to_string(),
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
@@ -228,14 +228,14 @@ impl Grippable for Body {
}
impl PropertyEditable for Body {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let size = acis_size_str(
self.acis_data.has_data(),
self.acis_data.sat_data.len(),
self.acis_data.sab_data.len(),
self.acis_data.is_binary,
);
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro(
@@ -269,7 +269,7 @@ impl PropertyEditable for Body {
self.silhouettes.len().to_string(),
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
+4 -4
View File
@@ -106,8 +106,8 @@ fn grips(spline: &Spline) -> Vec<GripDef> {
.collect()
}
fn properties(spline: &Spline) -> PropSection {
PropSection {
fn properties(spline: &Spline) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Degree", "degree", spline.degree.to_string()),
@@ -118,7 +118,7 @@ fn properties(spline: &Spline) -> PropSection {
),
ro("Fit Pts", "fit_pts", spline.fit_points.len().to_string()),
],
}
}]
}
fn apply_geom_prop(_spline: &mut Spline, _field: &str, _value: &str) {}
@@ -257,7 +257,7 @@ impl crate::entities::traits::Grippable for Spline {
}
impl crate::entities::traits::PropertyEditable for Spline {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+3 -3
View File
@@ -818,14 +818,14 @@ impl Grippable for Table {
}
impl PropertyEditable for Table {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let fmt_h = |oh: &Option<acadrust::types::Handle>| -> String {
match oh {
Some(h) if !h.is_null() => format!("{:X}", h.value()),
_ => "(none)".to_string(),
}
};
PropSection {
vec![PropSection {
title: "Table".into(),
props: vec![
ro("Rows", "tbl_rows", self.rows.len().to_string()),
@@ -921,7 +921,7 @@ impl PropertyEditable for Table {
),
),
],
}
}]
}
fn apply_geom_prop(&mut self, _field: &str, _value: &str) {}
+4 -4
View File
@@ -169,8 +169,8 @@ fn grips(t: &Text) -> Vec<GripDef> {
vec![square_grip(0, p)]
}
fn properties(t: &Text, text_style_names: &[String]) -> PropSection {
PropSection {
fn properties(t: &Text, text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Insert X", "ins_x", t.insertion_point.x),
@@ -224,7 +224,7 @@ fn properties(t: &Text, text_style_names: &[String]) -> PropSection {
},
},
],
}
}]
}
fn apply_geom_prop(t: &mut Text, field: &str, value: &str) {
@@ -377,7 +377,7 @@ impl Grippable for Text {
}
impl PropertyEditable for Text {
fn geometry_properties(&self, text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
properties(self, text_style_names)
}
+3 -3
View File
@@ -293,8 +293,8 @@ impl Grippable for Tolerance {
// ── PropertyEditable ──────────────────────────────────────────────────────────
impl PropertyEditable for Tolerance {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Text", "tol_text", self.text.clone()),
@@ -337,7 +337,7 @@ impl PropertyEditable for Tolerance {
),
),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+9 -7
View File
@@ -60,7 +60,9 @@ pub trait Grippable {
}
pub trait PropertyEditable {
fn geometry_properties(&self, text_style_names: &[String]) -> PropSection;
/// Type-specific property groups (Geometry, Misc, Text, …) shown after the
/// common General group. May be several groups; empty means none.
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection>;
fn apply_geom_prop(&mut self, field: &str, value: &str);
}
@@ -147,7 +149,7 @@ pub trait EntityTypeOps {
fn to_truck_entity(&self, document: &CadDocument) -> Option<TruckEntity>;
fn grips(&self) -> Vec<GripDef>;
fn grip_menu(&self, grip_id: usize) -> Vec<GripMenuItem>;
fn geometry_properties(&self, text_style_names: &[String]) -> Option<PropSection>;
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection>;
fn apply_geom_prop(&mut self, field: &str, value: &str);
fn apply_grip(&mut self, grip_id: usize, apply: GripApply);
fn apply_grip_menu(&mut self, grip_id: usize, action: GripMenuAction);
@@ -207,7 +209,7 @@ macro_rules! impl_entity_basics {
fn geometry_properties(
&self,
_text_style_names: &[String],
) -> $crate::scene::model::object::PropSection {
) -> Vec<$crate::scene::model::object::PropSection> {
properties(self)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -244,7 +246,7 @@ macro_rules! impl_entity_basics_with_text_styles {
fn geometry_properties(
&self,
text_style_names: &[String],
) -> $crate::scene::model::object::PropSection {
) -> Vec<$crate::scene::model::object::PropSection> {
properties(self, text_style_names)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
@@ -291,9 +293,9 @@ impl EntityTypeOps for EntityType {
)
}
fn geometry_properties(&self, text_style_names: &[String]) -> Option<PropSection> {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
dispatch!(self,
|e| Some(PropertyEditable::geometry_properties(e, text_style_names)),
|e| PropertyEditable::geometry_properties(e, text_style_names),
[
Line, Circle, Arc, Ellipse, LwPolyline, Polyline, Polyline2D,
Polyline3D, Ray, XLine, RasterImage, Wipeout,
@@ -303,7 +305,7 @@ impl EntityTypeOps for EntityType {
Viewport, Insert, Dimension, Leader, MultiLeader, Underlay,
Shape, Ole2Frame,
],
_ => None,
_ => vec![],
)
}
+3 -3
View File
@@ -146,13 +146,13 @@ impl Grippable for Underlay {
// ── PropertyEditable ──────────────────────────────────────────────────────────
impl PropertyEditable for Underlay {
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let type_str = match self.underlay_type {
acadrust::entities::UnderlayType::Pdf => "PDF",
acadrust::entities::UnderlayType::Dwf => "DWF",
acadrust::entities::UnderlayType::Dgn => "DGN",
};
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Type", "ul_type", type_str),
@@ -198,7 +198,7 @@ impl PropertyEditable for Underlay {
if self.clip_inverted { "Yes" } else { "No" },
),
],
}
}]
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
+3 -3
View File
@@ -116,7 +116,7 @@ fn grips(vp: &Viewport) -> Vec<GripDef> {
]
}
fn properties(vp: &Viewport) -> PropSection {
fn properties(vp: &Viewport) -> Vec<PropSection> {
let scale_opts: Vec<String> = STANDARD_SCALES.iter().map(|(s, _)| s.to_string()).collect();
let effective_scale =
crate::scene::vp_effective_scale(vp.custom_scale, vp.view_height, vp.height);
@@ -131,7 +131,7 @@ fn properties(vp: &Viewport) -> PropSection {
let shade_opts: Vec<String> = SHADE_PLOT_LABELS.iter().map(|s| s.to_string()).collect();
let current_shade = shade_plot_label(vp.shade_plot_mode).to_string();
PropSection {
vec![PropSection {
title: "Geometry".into(),
props: vec![
edit("Center X", "center_x", vp.center.x),
@@ -311,7 +311,7 @@ fn properties(vp: &Viewport) -> PropSection {
format!("{:#010x}", vp.ambient_color as u32),
),
],
}
}]
}
/// Identify which standard view matches the viewport's view direction.
+6 -3
View File
@@ -246,7 +246,7 @@ impl Scene {
.filter_map(|h| self.document.get_entity(h))
.find(|e| entity_type_name(e) == t);
if let Some(sample) = sample {
if let Some(section) = sample.geometry_properties(&text_style_names) {
for section in sample.geometry_properties(&text_style_names) {
for prop in section.props {
// Skip rows that don't sensibly compare via
// `entity_property_value` (read-only labels are
@@ -284,8 +284,11 @@ impl Scene {
.iter()
.map(|s| s.name.clone())
.collect();
let section = entity.geometry_properties(&text_style_names)?;
let prop = section.props.into_iter().find(|p| p.field == field)?;
let prop = entity
.geometry_properties(&text_style_names)
.into_iter()
.flat_map(|s| s.props)
.find(|p| p.field == field)?;
Some(match prop.value {
PropValue::ReadOnly(s) | PropValue::EditText(s) => s,
PropValue::LayerChoice(s) => s,
+8 -5
View File
@@ -17,11 +17,14 @@ pub fn properties_sectioned(
entity: &EntityType,
text_style_names: &[String],
) -> Vec<PropSection> {
let general = properties::general_section(entity);
let geometry = entity
.geometry_properties(text_style_names)
.unwrap_or_else(|| properties::fallback_properties(handle, entity));
vec![general, geometry]
let mut sections = vec![properties::general_section(entity)];
let groups = entity.geometry_properties(text_style_names);
if groups.is_empty() {
sections.push(properties::fallback_properties(handle, entity));
} else {
sections.extend(groups);
}
sections
}
pub fn apply_common_prop(entity: &mut EntityType, field: &str, value: &str) {