feat(grip): entity-specific popup menus for Line/Arc/Dimension
- Line: endpoint grips expose Stretch + Lengthen; midpoint exposes Stretch only. - Arc: endpoint exposes Stretch + Lengthen; midpoint exposes Stretch + Radius + Arc Length; centre exposes Stretch. - Dimension text grip exposes the full text-position vocabulary (Move with Dim Line / with Leader / Independent, Reset Text, Rotate Text, Above Dim Line, Center). Dim-line-position grip exposes Stretch + Reverse Arrows. Extension origins keep the default Stretch. - Each affected entity drops `impl_entity_basics!` and writes the three trait impls (Grippable, PropertyEditable, Transformable) manually so `grip_menu` / `apply_grip_menu` can override. - `apply_grip_menu` handles Reset Text (clear text override) and Center (snap text to midpoint of extension origins) inline; remaining actions stub to no-op pending the follow-up prompt / drag plumbing.
This commit is contained in:
parent
595ee3e245
commit
a4c65649e1
3 changed files with 179 additions and 2 deletions
|
|
@ -223,7 +223,58 @@ impl TruckConvertible for Arc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::impl_entity_basics!(Arc);
|
impl crate::entities::traits::Grippable for Arc {
|
||||||
|
fn grips(&self) -> Vec<GripDef> {
|
||||||
|
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<crate::scene::object::GripMenuItem> {
|
||||||
|
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 {
|
impl crate::entities::traits::MassPropsCalc for acadrust::entities::Arc {
|
||||||
fn mass_props(&self) -> crate::entities::traits::MassProps {
|
fn mass_props(&self) -> crate::entities::traits::MassProps {
|
||||||
|
|
|
||||||
|
|
@ -696,6 +696,86 @@ impl Grippable for Dimension {
|
||||||
}
|
}
|
||||||
self.base_mut().actual_measurement = self.measurement();
|
self.base_mut().actual_measurement = self.measurement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn grip_menu(
|
||||||
|
&self,
|
||||||
|
grip_id: usize,
|
||||||
|
) -> Vec<crate::scene::object::GripMenuItem> {
|
||||||
|
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 ─────────────────────────────────────────────────────────
|
// ── Tessellation ─────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,53 @@ impl TruckConvertible for Line {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::impl_entity_basics!(Line);
|
impl crate::entities::traits::Grippable for Line {
|
||||||
|
fn grips(&self) -> Vec<GripDef> {
|
||||||
|
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<crate::scene::object::GripMenuItem> {
|
||||||
|
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 {
|
impl crate::entities::traits::MassPropsCalc for acadrust::entities::Line {
|
||||||
fn mass_props(&self) -> crate::entities::traits::MassProps {
|
fn mass_props(&self) -> crate::entities::traits::MassProps {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue