use acadrust::entities::{SectionSymbol, ViewBorder}; use crate::t; use crate::command::EntityTransform; use crate::entities::common::{edit_angle_prop, edit_prop, parse_f64, ro_prop, square_grip}; use crate::entities::traits::{Grippable, PropertyEditable, Transformable}; use crate::scene::model::object::{GripApply, GripDef, PropSection}; fn handle_text(handle: acadrust::Handle) -> String { if handle.is_null() { "None".to_string() } else { format!("{:X}", handle.value()) } } fn vector_text(vector: &acadrust::types::Vector3) -> String { format!("{:.6}, {:.6}, {:.6}", vector.x, vector.y, vector.z) } fn apply_entity_transform(entity: &mut T, transform: &EntityTransform) { crate::scene::view::transform::apply_standard_entity_transform( entity, transform, |entity, first, second| { entity.apply_transform( &crate::scene::view::transform::reflection_about_xy_line(first, second), ); }, ); } impl Grippable for SectionSymbol { fn grips(&self) -> Vec { self.points .iter() .enumerate() .map(|(index, point)| { square_grip( index, glam::DVec3::new(point.point.x, point.point.y, point.point.z), ) }) .collect() } fn apply_grip(&mut self, grip_id: usize, apply: GripApply) { let Some(point) = self.points.get_mut(grip_id) else { return; }; match apply { GripApply::Translate(delta) => { point.point.x += delta.x; point.point.y += delta.y; point.point.z += delta.z; } GripApply::Absolute(position) => { point.point = acadrust::types::Vector3::new(position.x, position.y, position.z); } } self.sync_display_fields(); } } impl PropertyEditable for SectionSymbol { fn geometry_properties(&self, _text_style_names: &[String]) -> Vec { let point_data = self .points .iter() .enumerate() .map(|(index, point)| { format!( "{}: point [{}]; bulge {:.6}; label {:?}; offset [{}]; flag {}", index + 1, vector_text(&point.point), point.bulge, point.label, vector_text(&point.label_offset), point.raw_flag_280 ) }) .collect::>() .join("\n"); vec![ PropSection { title: t!("Section Symbol").into_owned(), props: vec![ edit_prop(t!("Symbol Scale").as_ref(), "section_scale", self.symbol_scale), ro_prop(t!("View Symbol Version").as_ref(), "section_view_version", self.view_symbol_version.to_string(), ), ro_prop(t!("Version").as_ref(), "section_version", self.version.to_string()), ro_prop(t!("Style").as_ref(), "section_style", handle_text(self.style_handle), ), ro_prop(t!("View Representation").as_ref(), "section_view_rep", handle_text(self.view_rep_handle), ), ro_prop(t!("View Symbol Flags").as_ref(), "section_view_flags", self.raw_view_symbol_70.to_string(), ), ro_prop(t!("Point Count").as_ref(), "section_point_count", self.points.len().to_string(), ), ro_prop(t!("Stored Point Counts").as_ref(), "section_raw_counts", format!( "{}, {}, flags {}", self.raw_point_count_90, self.raw_point_record_count, self.raw_flags_90 ), ), ro_prop(t!("Identifier").as_ref(), "section_label", self.label.clone()), ], }, PropSection { title: t!("Section Points").into_owned(), props: vec![ro_prop(t!("Records").as_ref(), "section_points", point_data)], }, ] } fn apply_geom_prop(&mut self, field: &str, value: &str) { if field == "section_scale" { if let Some(value) = parse_f64(value) { self.symbol_scale = value.max(0.0); } } } } impl Transformable for SectionSymbol { fn apply_transform(&mut self, transform: &EntityTransform) { apply_entity_transform(self, transform); self.sync_display_fields(); } } impl Grippable for ViewBorder { fn grips(&self) -> Vec { vec![ square_grip(0, glam::DVec3::new(self.min[0], self.min[1], 0.0)), square_grip(1, glam::DVec3::new(self.max[0], self.max[1], 0.0)), square_grip(2, glam::DVec3::new(self.center[0], self.center[1], 0.0)), ] } fn apply_grip(&mut self, grip_id: usize, apply: GripApply) { let delta = match apply { GripApply::Translate(delta) => delta, GripApply::Absolute(position) => { let current = match grip_id { 0 => glam::DVec3::new(self.min[0], self.min[1], 0.0), 1 => glam::DVec3::new(self.max[0], self.max[1], 0.0), 2 => glam::DVec3::new(self.center[0], self.center[1], 0.0), _ => return, }; position - current } }; match grip_id { 0 => { self.min[0] += delta.x; self.min[1] += delta.y; } 1 => { self.max[0] += delta.x; self.max[1] += delta.y; } 2 => { self.min[0] += delta.x; self.min[1] += delta.y; self.max[0] += delta.x; self.max[1] += delta.y; } _ => return, } self.center = [ (self.min[0] + self.max[0]) * 0.5, (self.min[1] + self.max[1]) * 0.5, ]; } } impl PropertyEditable for ViewBorder { fn geometry_properties(&self, _text_style_names: &[String]) -> Vec { vec![PropSection { title: t!("Drawing View").into_owned(), props: vec![ edit_prop(t!("Center X").as_ref(), "view_border_x", self.center[0]), edit_prop(t!("Center Y").as_ref(), "view_border_y", self.center[1]), ro_prop(t!("Width").as_ref(), "view_border_width", format!("{:.6}", self.max[0] - self.min[0]), ), ro_prop(t!("Height").as_ref(), "view_border_height", format!("{:.6}", self.max[1] - self.min[1]), ), edit_prop(t!("Scale").as_ref(), "view_border_scale", self.scale), edit_angle_prop(t!("Rotation").as_ref(), "view_border_rotation", self.rotation_angle.to_degrees(), ), ro_prop(t!("Version").as_ref(), "view_border_version", self.version.to_string()), ro_prop(t!("Active Viewport").as_ref(), "view_border_viewport", handle_text(self.active_viewport), ), ro_prop(t!("Scale Object").as_ref(), "view_border_scale_handle", handle_text(self.scale_handle), ), ], }] } fn apply_geom_prop(&mut self, field: &str, value: &str) { let Some(value) = parse_f64(value) else { return; }; match field { "view_border_x" => { let delta = value - self.center[0]; self.min[0] += delta; self.max[0] += delta; self.center[0] = value; } "view_border_y" => { let delta = value - self.center[1]; self.min[1] += delta; self.max[1] += delta; self.center[1] = value; } "view_border_scale" => self.scale = value.max(0.0), "view_border_rotation" => self.rotation_angle = value.to_radians(), _ => {} } } } impl Transformable for ViewBorder { fn apply_transform(&mut self, transform: &EntityTransform) { apply_entity_transform(self, transform); } }