diff --git a/src/entities/arc.rs b/src/entities/arc.rs index 4a42df3a9..8fa5a0dfe 100644 --- a/src/entities/arc.rs +++ b/src/entities/arc.rs @@ -223,7 +223,58 @@ impl TruckConvertible for Arc { } } -crate::impl_entity_basics!(Arc); +impl crate::entities::traits::Grippable for Arc { + fn grips(&self) -> Vec { + grips(self) + } + fn apply_grip(&mut self, grip_id: usize, apply: GripApply) { + apply_grip(self, grip_id, apply); + } + fn grip_menu( + &self, + grip_id: usize, + ) -> Vec { + use crate::scene::object::{GripMenuAction, GripMenuItem}; + match grip_id { + 0 => vec![GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }], + 3 => vec![ + GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }, + GripMenuItem { label: "Radius", action: GripMenuAction::Radius }, + GripMenuItem { label: "Arc Length", action: GripMenuAction::ArcLength }, + ], + _ => vec![ + GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }, + GripMenuItem { label: "Lengthen", action: GripMenuAction::Lengthen }, + ], + } + } + fn apply_grip_menu( + &mut self, + _grip_id: usize, + _action: crate::scene::object::GripMenuAction, + ) { + // Radius / Arc Length / Lengthen all need a follow-up prompt + // (numeric distance / length / radius) — Phase 3. + } +} + +impl crate::entities::traits::PropertyEditable for Arc { + fn geometry_properties( + &self, + _text_style_names: &[String], + ) -> PropSection { + properties(self) + } + fn apply_geom_prop(&mut self, field: &str, value: &str) { + apply_geom_prop(self, field, value); + } +} + +impl crate::entities::traits::Transformable for Arc { + fn apply_transform(&mut self, t: &EntityTransform) { + apply_transform(self, t); + } +} impl crate::entities::traits::MassPropsCalc for acadrust::entities::Arc { fn mass_props(&self) -> crate::entities::traits::MassProps { diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index 50ffadf31..f7cde4b8d 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -696,6 +696,86 @@ impl Grippable for Dimension { } self.base_mut().actual_measurement = self.measurement(); } + + fn grip_menu( + &self, + grip_id: usize, + ) -> Vec { + use crate::scene::object::{GripMenuAction, GripMenuItem}; + let (dim_line_grip, text_grip) = match self { + Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3), + Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2), + Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => (3, 4), + Dimension::Ordinate(_) => (0, 3), + }; + if grip_id == text_grip { + vec![ + GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }, + GripMenuItem { label: "Move with Dim Line", action: GripMenuAction::MoveWithDimLine }, + GripMenuItem { label: "Move with Leader", action: GripMenuAction::MoveWithLeader }, + GripMenuItem { label: "Move Independent", action: GripMenuAction::MoveIndependent }, + GripMenuItem { label: "Reset Text", action: GripMenuAction::ResetText }, + GripMenuItem { label: "Rotate Text", action: GripMenuAction::RotateText }, + GripMenuItem { label: "Above Dim Line", action: GripMenuAction::AboveDimLine }, + GripMenuItem { label: "Center", action: GripMenuAction::Center }, + ] + } else if grip_id == dim_line_grip { + vec![ + GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }, + GripMenuItem { label: "Reverse Arrows", action: GripMenuAction::ReverseArrows }, + ] + } else { + vec![GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }] + } + } + + fn apply_grip_menu( + &mut self, + grip_id: usize, + action: crate::scene::object::GripMenuAction, + ) { + use crate::scene::object::GripMenuAction as A; + let (_dim_line_grip, text_grip) = match self { + Dimension::Linear(_) | Dimension::Aligned(_) => (2, 3), + Dimension::Radius(_) | Dimension::Diameter(_) => (1, 2), + Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => (3, 4), + Dimension::Ordinate(_) => (0, 3), + }; + match action { + A::ResetText if grip_id == text_grip => { + // Drop any text-position override — leave it to the + // renderer to recompute from the dim style. + let b = self.base_mut(); + b.text_middle_point.x = 0.0; + b.text_middle_point.y = 0.0; + b.text_middle_point.z = 0.0; + } + A::Center if grip_id == text_grip => { + // Snap text to the centre of the dimension line. + // Approximate as midpoint of first/second extension + // origins for Linear / Aligned dimensions. + match self { + Dimension::Linear(d) => { + let mx = (d.first_point.x + d.second_point.x) * 0.5; + let my = (d.first_point.y + d.second_point.y) * 0.5; + d.base.text_middle_point.x = mx; + d.base.text_middle_point.y = my; + } + Dimension::Aligned(d) => { + let mx = (d.first_point.x + d.second_point.x) * 0.5; + let my = (d.first_point.y + d.second_point.y) * 0.5; + d.base.text_middle_point.x = mx; + d.base.text_middle_point.y = my; + } + _ => {} + } + } + // Stretch / Move-variants / Reverse Arrows / Rotate Text / + // Above Dim Line need either a follow-up drag or a numeric + // prompt — wired to default Stretch behaviour for now. + _ => {} + } + } } // ── Tessellation ───────────────────────────────────────────────────────── diff --git a/src/entities/line.rs b/src/entities/line.rs index a37961ae2..2227c6d4e 100644 --- a/src/entities/line.rs +++ b/src/entities/line.rs @@ -156,7 +156,53 @@ impl TruckConvertible for Line { } } -crate::impl_entity_basics!(Line); +impl crate::entities::traits::Grippable for Line { + fn grips(&self) -> Vec { + grips(self) + } + fn apply_grip(&mut self, grip_id: usize, apply: GripApply) { + apply_grip(self, grip_id, apply); + } + fn grip_menu( + &self, + grip_id: usize, + ) -> Vec { + use crate::scene::object::{GripMenuAction, GripMenuItem}; + if grip_id == 2 { + vec![GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }] + } else { + vec![ + GripMenuItem { label: "Stretch", action: GripMenuAction::Stretch }, + GripMenuItem { label: "Lengthen", action: GripMenuAction::Lengthen }, + ] + } + } + fn apply_grip_menu( + &mut self, + _grip_id: usize, + _action: crate::scene::object::GripMenuAction, + ) { + // Lengthen requires a follow-up distance prompt — Phase 3. + } +} + +impl crate::entities::traits::PropertyEditable for Line { + fn geometry_properties( + &self, + _text_style_names: &[String], + ) -> PropSection { + properties(self) + } + fn apply_geom_prop(&mut self, field: &str, value: &str) { + apply_geom_prop(self, field, value); + } +} + +impl crate::entities::traits::Transformable for Line { + fn apply_transform(&mut self, t: &EntityTransform) { + apply_transform(self, t); + } +} impl crate::entities::traits::MassPropsCalc for acadrust::entities::Line { fn mass_props(&self) -> crate::entities::traits::MassProps {