diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index e45e8ca8f..bda0e71b1 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -840,6 +840,10 @@ impl OpenCADStudio { fn apply_cmd_result_inner(&mut self, result: CmdResult) -> Task { let i = self.active_tab; + let preserve_commit_layer = self.tabs[i] + .active_cmd + .as_ref() + .is_some_and(|command| command.preserve_commit_layer()); match result { CmdResult::NeedPoint => { // ATTEDIT finished its entity pick: hand the chosen block off to @@ -935,7 +939,11 @@ impl OpenCADStudio { ); let association_enabled = self.tabs[i].scene.document.header.dimension_associativity == 2; - let committed = self.commit_entity_handle(entity); + let committed = if preserve_commit_layer { + self.commit_entity_handle_preserve_layer(entity) + } else { + self.commit_entity_handle(entity) + }; if is_associative_dimension && association_enabled { if let Some(handle) = committed { let sources = self.tabs[i] @@ -973,7 +981,11 @@ impl OpenCADStudio { .all(|entity| self.delta_add_safe(i, entity)); let pending = self.begin_undo(i, label, entities.len(), delta_safe); for entity in entities { - self.commit_entity(entity); + if preserve_commit_layer { + let _ = self.commit_entity_handle_preserve_layer(entity); + } else { + self.commit_entity(entity); + } } self.tabs[i].dirty = true; self.tabs[i].scene.clear_preview_wire(); diff --git a/src/app/commands/dim.rs b/src/app/commands/dim.rs index b697b71df..d03e7cfa3 100644 --- a/src/app/commands/dim.rs +++ b/src/app/commands/dim.rs @@ -1238,8 +1238,18 @@ impl OpenCADStudio { .map(|e| (h, e)) }) .collect(); + let initial_edges: Vec = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .filter_map(|(handle, entity)| { + crate::modules::draw::modify::trim::is_trim_boundary_entity(&entity) + .then_some(handle) + }) + .collect(); let all_entities: Vec<_> = entities.into_iter().map(|(_, e)| e).collect(); - let new_cmd = TrimCommand::new(all_entities); + let new_cmd = + TrimCommand::with_cutting_edges(all_entities, initial_edges); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } diff --git a/src/app/properties.rs b/src/app/properties.rs index 2afb21660..a08166252 100644 --- a/src/app/properties.rs +++ b/src/app/properties.rs @@ -2596,14 +2596,33 @@ impl OpenCADStudio { &mut self, entity: acadrust::EntityType, ) -> Option { - self.commit_entity_handle_with_dimension_policy(entity, false) + self.commit_entity_handle_with_policies(entity, false, false) } - /// Commit an entity, optionally preserving its source dimension style. pub(super) fn commit_entity_handle_with_dimension_policy( + &mut self, + entity: acadrust::EntityType, + preserve_dimension_layer_and_style: bool, + ) -> Option { + self.commit_entity_handle_with_policies( + entity, + preserve_dimension_layer_and_style, + false, + ) + } + + pub(super) fn commit_entity_handle_preserve_layer( + &mut self, + entity: acadrust::EntityType, + ) -> Option { + self.commit_entity_handle_with_policies(entity, false, true) + } + + fn commit_entity_handle_with_policies( &mut self, mut entity: acadrust::EntityType, preserve_dimension_layer_and_style: bool, + preserve_entity_layer: bool, ) -> Option { let i = self.active_tab; let tracks_dimension_chain = matches!( @@ -2692,7 +2711,7 @@ impl OpenCADStudio { }; if let Some(layer) = explicit_mleader_layer { entity.as_entity_mut().set_layer(layer); - } else { + } else if !preserve_entity_layer { let layer = &self.tabs[i].active_layer; if layer != "0" || entity.as_entity().layer().is_empty() { entity.as_entity_mut().set_layer(layer.clone()); diff --git a/src/command.rs b/src/command.rs index cc25ff607..518539fb6 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1734,6 +1734,11 @@ impl InputKind { } pub trait CadCommand: Send { + /// Keep the layer already carried by entities committed by this command + /// instead of replacing it with the current drawing layer. + fn preserve_commit_layer(&self) -> bool { + false + } /// Short name shown in the command line prompt, e.g. `"LINE"`. #[allow(dead_code)] fn name(&self) -> &'static str; diff --git a/src/modules/draw/modify/offset.rs b/src/modules/draw/modify/offset.rs index 20a988ac6..a2118f12b 100644 --- a/src/modules/draw/modify/offset.rs +++ b/src/modules/draw/modify/offset.rs @@ -514,6 +514,9 @@ impl OffsetCommand { } impl CadCommand for OffsetCommand { + fn preserve_commit_layer(&self) -> bool { + true + } fn name(&self) -> &'static str { "OFFSET" } diff --git a/src/modules/draw/modify/trim.rs b/src/modules/draw/modify/trim.rs index 039db2b9a..d1341013a 100644 --- a/src/modules/draw/modify/trim.rs +++ b/src/modules/draw/modify/trim.rs @@ -149,7 +149,22 @@ impl Geo { } } } - +pub fn is_trim_boundary_entity(entity: &EntityType) -> bool { + matches!( + entity, + EntityType::Line(_) + | EntityType::Arc(_) + | EntityType::Circle(_) + | EntityType::Ellipse(_) + | EntityType::Ray(_) + | EntityType::XLine(_) + | EntityType::Spline(_) + | EntityType::LwPolyline(_) + | EntityType::Polyline(_) + | EntityType::Polyline2D(_) + | EntityType::Polyline3D(_) + ) +} fn build_geos(entities: &[EntityType]) -> Vec { let mut out = Vec::new(); for e in entities { @@ -2169,21 +2184,33 @@ pub struct TrimCommand { impl TrimCommand { pub fn new(all_entities: Vec) -> Self { + Self::with_cutting_edges(all_entities, Vec::new()) + } + + pub fn with_cutting_edges( + all_entities: Vec, + initial_edges: Vec, + ) -> Self { let all_entities: Vec = all_entities .iter() .map(entity_with_lwpolyline_world_xy) .collect(); + let entity_index = ModifyEntityIndex::build(&all_entities); - let geos = build_geos(&all_entities); - Self { + + let mut cmd = Self { all_entities, entity_index, - geos, + geos: Vec::new(), mode: TrimMode::Pick, - edge_set: Vec::new(), + edge_set: initial_edges, implied_edges: false, shift: false, - } + }; + + cmd.rebuild_geos(); + + cmd } /// Boundary geometry from the edge selection (or everything when none),