From ca07268c7c4af44ff53963960a2d7e880c3457a3 Mon Sep 17 00:00:00 2001 From: Hakan Date: Tue, 12 May 2026 10:36:15 +0300 Subject: [PATCH] cargo fmt --- src/app/cmd_result.rs | 577 ++++-- src/app/commands.rs | 2516 ++++++++++++++++------- src/app/document.rs | 14 +- src/app/helpers.rs | 60 +- src/app/history.rs | 24 +- src/app/layers.rs | 86 +- src/app/mod.rs | 214 +- src/app/properties.rs | 59 +- src/app/update.rs | 1545 ++++++++++---- src/app/view.rs | 912 +++++--- src/command/mod.rs | 14 +- src/entities/arc.rs | 24 +- src/entities/attribute.rs | 20 +- src/entities/circle.rs | 36 +- src/entities/dimension.rs | 50 +- src/entities/ellipse.rs | 4 +- src/entities/hatch.rs | 47 +- src/entities/insert.rs | 6 +- src/entities/leader.rs | 47 +- src/entities/line.rs | 33 +- src/entities/lwpolyline.rs | 116 +- src/entities/mesh.rs | 45 +- src/entities/mline.rs | 35 +- src/entities/mod.rs | 6 +- src/entities/multileader.rs | 222 +- src/entities/ole2frame.rs | 50 +- src/entities/polyline.rs | 104 +- src/entities/raster_image.rs | 57 +- src/entities/ray.rs | 32 +- src/entities/shape.rs | 40 +- src/entities/solid.rs | 26 +- src/entities/solid3d.rs | 54 +- src/entities/spline.rs | 6 +- src/entities/table.rs | 53 +- src/entities/text.rs | 23 +- src/entities/text_support.rs | 59 +- src/entities/tolerance.rs | 84 +- src/entities/traits.rs | 163 +- src/entities/viewport.rs | 190 +- src/io/mod.rs | 39 +- src/io/obj.rs | 24 +- src/io/pdf_export.rs | 94 +- src/io/plot_style.rs | 52 +- src/io/print_to_printer.rs | 2 +- src/io/step.rs | 137 +- src/io/stl.rs | 5 +- src/io/xref.rs | 6 +- src/linetypes.rs | 20 +- src/modules/annotate/aligned_dim.rs | 45 +- src/modules/annotate/angular_dim.rs | 31 +- src/modules/annotate/ddedit.rs | 44 +- src/modules/annotate/diameter_dim.rs | 32 +- src/modules/annotate/dim_baseline.rs | 16 +- src/modules/annotate/dim_continue.rs | 16 +- src/modules/annotate/dimbreak.rs | 24 +- src/modules/annotate/dimedit.rs | 24 +- src/modules/annotate/dimjogline.rs | 16 +- src/modules/annotate/dimspace.rs | 39 +- src/modules/annotate/dimtedit.rs | 30 +- src/modules/annotate/leader_cmd.rs | 91 +- src/modules/annotate/linear_dim.rs | 10 +- src/modules/annotate/mleader_cmd.rs | 75 +- src/modules/annotate/mleader_edit.rs | 218 +- src/modules/annotate/mod.rs | 95 +- src/modules/annotate/ordinate_dim.rs | 16 +- src/modules/annotate/qdim.rs | 25 +- src/modules/annotate/radius_dim.rs | 10 +- src/modules/annotate/table_cmd.rs | 43 +- src/modules/annotate/tolerance_cmd.rs | 10 +- src/modules/home/draw/attdef.rs | 66 +- src/modules/home/draw/donut.rs | 19 +- src/modules/home/draw/ellipse.rs | 10 +- src/modules/home/draw/hatchedit.rs | 64 +- src/modules/home/draw/mline.rs | 44 +- src/modules/home/draw/mod.rs | 2 +- src/modules/home/draw/polyline.rs | 16 +- src/modules/home/draw/raster_image.rs | 12 +- src/modules/home/draw/revcloud.rs | 27 +- src/modules/home/draw/wipeout.rs | 60 +- src/modules/home/inquiry/divide.rs | 150 +- src/modules/home/layers/make_current.rs | 4 +- src/modules/home/layers/match_layer.rs | 4 +- src/modules/home/mod.rs | 68 +- src/modules/home/modify/align.rs | 35 +- src/modules/home/modify/array.rs | 164 +- src/modules/home/modify/attedit.rs | 55 +- src/modules/home/modify/break_cmd.rs | 87 +- src/modules/home/modify/explode.rs | 59 +- src/modules/home/modify/fillet.rs | 336 ++- src/modules/home/modify/join.rs | 128 +- src/modules/home/modify/lengthen.rs | 210 +- src/modules/home/modify/mod.rs | 14 +- src/modules/home/modify/offset.rs | 69 +- src/modules/home/modify/pedit.rs | 53 +- src/modules/home/modify/refedit.rs | 10 +- src/modules/home/modify/spline_ops.rs | 41 +- src/modules/home/modify/splinedit.rs | 43 +- src/modules/home/modify/stretch.rs | 87 +- src/modules/home/modify/trim.rs | 889 ++++++-- src/modules/insert/attdef.rs | 7 +- src/modules/insert/attedit.rs | 7 +- src/modules/insert/attman.rs | 7 +- src/modules/insert/attsync.rs | 7 +- src/modules/insert/base_point.rs | 7 +- src/modules/insert/content_browser.rs | 10 +- src/modules/insert/design_center.rs | 7 +- src/modules/insert/edit_block.rs | 7 +- src/modules/insert/insert_block.rs | 33 +- src/modules/insert/landxml.rs | 7 +- src/modules/insert/mod.rs | 36 +- src/modules/insert/mview_block.rs | 7 +- src/modules/insert/pc_attach.rs | 7 +- src/modules/insert/snap_underlays.rs | 10 +- src/modules/insert/solid3d_cmds.rs | 376 +++- src/modules/insert/underlay_frames.rs | 10 +- src/modules/insert/underlay_layers.rs | 10 +- src/modules/insert/wblock.rs | 9 +- src/modules/insert/xadjust.rs | 7 +- src/modules/insert/xattach.rs | 9 +- src/modules/insert/xclip.rs | 7 +- src/modules/layout/vplayer.rs | 12 +- src/modules/manage/audit.rs | 7 +- src/modules/manage/cui_export.rs | 7 +- src/modules/manage/cui_import.rs | 7 +- src/modules/manage/edit_aliases.rs | 7 +- src/modules/manage/find_nonpurgeable.rs | 11 +- src/modules/manage/mod.rs | 24 +- src/modules/manage/overkill.rs | 7 +- src/modules/manage/purge.rs | 7 +- src/modules/manage/user_interface.rs | 10 +- src/modules/mod.rs | 5 +- src/modules/view/cascade.rs | 7 +- src/modules/view/file_tabs.rs | 7 +- src/modules/view/hidden.rs | 7 +- src/modules/view/layout_tabs.rs | 7 +- src/modules/view/mod.rs | 30 +- src/modules/view/navbar.rs | 7 +- src/modules/view/orbit.rs | 7 +- src/modules/view/ortho.rs | 7 +- src/modules/view/pan.rs | 7 +- src/modules/view/persp.rs | 7 +- src/modules/view/plot_window.rs | 16 +- src/modules/view/properties_palette.rs | 7 +- src/modules/view/sheetset.rs | 7 +- src/modules/view/solid.rs | 7 +- src/modules/view/tile_horiz.rs | 7 +- src/modules/view/tile_vert.rs | 7 +- src/modules/view/tool_palettes.rs | 7 +- src/modules/view/ucs_icon.rs | 7 +- src/modules/view/view_front.rs | 7 +- src/modules/view/view_iso.rs | 7 +- src/modules/view/view_right.rs | 7 +- src/modules/view/view_top.rs | 7 +- src/modules/view/viewcube.rs | 7 +- src/modules/view/vports_config.rs | 7 +- src/modules/view/vports_join.rs | 7 +- src/modules/view/vports_named.rs | 7 +- src/modules/view/vports_restore.rs | 10 +- src/modules/view/wireframe.rs | 7 +- src/modules/view/xray.rs | 7 +- src/modules/view/zoom_ext.rs | 7 +- src/modules/view/zoom_in.rs | 7 +- src/modules/view/zoom_out.rs | 7 +- src/scene/acad_to_truck.rs | 2 +- src/scene/camera.rs | 2 +- src/scene/complex_lt.rs | 25 +- src/scene/cxf.rs | 87 +- src/scene/grip.rs | 12 +- src/scene/hit_test.rs | 44 +- src/scene/image_model.rs | 9 +- src/scene/mod.rs | 1291 +++++++----- src/scene/paper_canvas.rs | 22 +- src/scene/pipeline/face3d_gpu.rs | 18 +- src/scene/pipeline/hatch_gpu.rs | 4 +- src/scene/pipeline/image_gpu.rs | 35 +- src/scene/pipeline/mod.rs | 64 +- src/scene/pipeline/viewcube.rs | 80 +- src/scene/pipeline/wire_gpu.rs | 41 +- src/scene/render.rs | 20 +- src/scene/solid3d_tess.rs | 97 +- src/scene/tessellate.rs | 396 +++- src/scene/transform.rs | 5 +- src/scene/truck_tess.rs | 6 +- src/scene/viewport_pane.rs | 21 +- src/scene/wire_model.rs | 8 +- src/snap/mod.rs | 45 +- src/ui/about.rs | 120 +- src/ui/dimstyle.rs | 458 ++++- src/ui/layers.rs | 462 ++++- src/ui/layout_manager.rs | 266 ++- src/ui/mlstyle.rs | 243 ++- src/ui/mod.rs | 2 +- src/ui/overlay.rs | 258 ++- src/ui/page_setup.rs | 323 ++- src/ui/plotstyle.rs | 308 ++- src/ui/properties.rs | 212 +- src/ui/ribbon/mod.rs | 331 ++- src/ui/ribbon/widgets.rs | 587 ++++-- src/ui/scale_popup.rs | 66 +- src/ui/shortcuts.rs | 155 +- src/ui/snap_popup.rs | 2 +- src/ui/statusbar.rs | 159 +- src/ui/tablestyle.rs | 208 +- src/ui/textstyle.rs | 310 ++- 204 files changed, 13997 insertions(+), 5525 deletions(-) diff --git a/src/app/cmd_result.rs b/src/app/cmd_result.rs index 7efe94510..b4e9265ab 100644 --- a/src/app/cmd_result.rs +++ b/src/app/cmd_result.rs @@ -1,4 +1,4 @@ -use super::{H7CAD, Message}; +use super::{Message, H7CAD}; use crate::command::CmdResult; use acadrust::Handle; use iced::Task; @@ -125,9 +125,16 @@ impl H7CAD { self.tabs[i].snap_result = None; self.restore_pre_cmd_tangent(); } - CmdResult::CreateBlock { handles, name, base } => { + CmdResult::CreateBlock { + handles, + name, + base, + } => { self.push_undo_snapshot(i, "BLOCK"); - match self.tabs[i].scene.create_block_from_entities(&handles, &name, base) { + match self.tabs[i] + .scene + .create_block_from_entities(&handles, &name, base) + { Ok(insert_handle) => { self.tabs[i].dirty = true; self.tabs[i].scene.deselect_all(); @@ -215,7 +222,8 @@ impl H7CAD { self.tabs[i].dirty = true; self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; - self.command_line.push_output("ATTEDIT Attribute values updated."); + self.command_line + .push_output("ATTEDIT Attribute values updated."); return Task::none(); } } @@ -235,7 +243,9 @@ impl H7CAD { ); self.tabs[i].dirty = true; let prompt = self.tabs[i].active_cmd.as_ref().map(|c| c.prompt()); - if let Some(p) = prompt { self.command_line.push_info(&p); } + if let Some(p) = prompt { + self.command_line.push_info(&p); + } return Task::none(); } } @@ -244,7 +254,9 @@ impl H7CAD { if new_entities.len() == 1 { if let acadrust::EntityType::XLine(ref xl) = new_entities[0] { let layer = xl.common.layer.clone(); - if layer.starts_with("__DIMBREAK__") || layer.starts_with("__DIMBREAK_AUTO__") { + if layer.starts_with("__DIMBREAK__") + || layer.starts_with("__DIMBREAK_AUTO__") + { // DIMBREAK is a geometry operation we approximate by // recording a note on the dimension; full intersection logic // requires render geometry. For now, just undo-snapshot and log. @@ -280,7 +292,8 @@ impl H7CAD { apply_mleader_align(&mut self.tabs[i].scene, encoded); } self.push_undo_snapshot(i, "MLEADERALIGN"); - self.command_line.push_output("MLEADERALIGN Leaders aligned."); + self.command_line + .push_output("MLEADERALIGN Leaders aligned."); self.tabs[i].dirty = true; self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; @@ -291,7 +304,8 @@ impl H7CAD { apply_mleader_collect(&mut self.tabs[i].scene, encoded); } self.push_undo_snapshot(i, "MLEADERCOLLECT"); - self.command_line.push_output("MLEADERCOLLECT Leaders collected."); + self.command_line + .push_output("MLEADERCOLLECT Leaders collected."); self.tabs[i].dirty = true; self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; @@ -321,15 +335,22 @@ impl H7CAD { let attdefs: Vec<(String, String, String)> = { let doc = &self.tabs[i].scene.document; if let Some(br) = doc.block_records.get(&block_name) { - br.entity_handles.iter().filter_map(|&h| { - if let Some(acadrust::EntityType::AttributeDefinition(ad)) = - doc.get_entity(h) - { - Some((ad.tag.clone(), ad.prompt.clone(), ad.default_value.clone())) - } else { - None - } - }).collect() + br.entity_handles + .iter() + .filter_map(|&h| { + if let Some(acadrust::EntityType::AttributeDefinition(ad)) = + doc.get_entity(h) + { + Some(( + ad.tag.clone(), + ad.prompt.clone(), + ad.default_value.clone(), + )) + } else { + None + } + }) + .collect() } else { vec![] } @@ -337,7 +358,9 @@ impl H7CAD { if attdefs.is_empty() { // No attribute definitions — commit the INSERT directly. - let entity = self.tabs[i].active_cmd.as_mut() + let entity = self.tabs[i] + .active_cmd + .as_mut() .and_then(|c| c.attreq_take_insert()); if let Some(entity) = entity { let label = self.history_label_from_active_cmd(i, "INSERT"); @@ -382,7 +405,9 @@ impl H7CAD { self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; self.tabs[i].scene.clear_preview_wire(); - let src_layer = self.tabs[i].scene.document + let src_layer = self.tabs[i] + .scene + .document .get_entity(src) .map(|e| e.common().layer.clone()); if let Some(layer) = src_layer { @@ -393,7 +418,8 @@ impl H7CAD { } } self.tabs[i].dirty = true; - self.command_line.push_info(&format!("Layer matched to \"{layer}\".")); + self.command_line + .push_info(&format!("Layer matched to \"{layer}\".")); self.sync_ribbon_layers(); } else { self.command_line.push_error("Source object not found."); @@ -406,7 +432,13 @@ impl H7CAD { let props = self.tabs[i].scene.document.get_entity(src).map(|e| { let c = e.common(); - (c.layer.clone(), c.color, c.linetype.clone(), c.linetype_scale, c.line_weight) + ( + c.layer.clone(), + c.color, + c.linetype.clone(), + c.linetype_scale, + c.line_weight, + ) }); if let Some((layer, color, linetype, lt_scale, lw)) = props { @@ -422,9 +454,8 @@ impl H7CAD { } self.tabs[i].dirty = true; self.refresh_properties(); - self.command_line.push_info( - &format!("Properties matched to {} object(s).", dest.len()) - ); + self.command_line + .push_info(&format!("Properties matched to {} object(s).", dest.len())); } else { self.command_line.push_error("Source object not found."); } @@ -440,7 +471,9 @@ impl H7CAD { let translate = crate::command::EntityTransform::Translate(delta); self.push_undo_snapshot(i, "PASTECLIP"); let count = self.clipboard.len(); - let new_handles: Vec = self.clipboard.clone() + let new_handles: Vec = self + .clipboard + .clone() .into_iter() .map(|mut entity| { crate::scene::dispatch::apply_transform(&mut entity, &translate); @@ -455,7 +488,8 @@ impl H7CAD { } self.tabs[i].dirty = true; self.refresh_properties(); - self.command_line.push_info(&format!("{count} object(s) pasted.")); + self.command_line + .push_info(&format!("{count} object(s) pasted.")); } } CmdResult::CreateGroup { handles, name } => { @@ -465,7 +499,8 @@ impl H7CAD { self.push_undo_snapshot(i, "GROUP"); self.tabs[i].scene.create_group(name.clone(), handles); self.tabs[i].dirty = true; - self.command_line.push_info(&format!("Group \"{}\" created.", name)); + self.command_line + .push_info(&format!("Group \"{}\" created.", name)); } CmdResult::DeleteGroups { handles } => { self.tabs[i].active_cmd = None; @@ -475,24 +510,40 @@ impl H7CAD { let count = self.tabs[i].scene.delete_groups_containing(&handles); self.tabs[i].dirty = true; if count > 0 { - self.command_line.push_info(&format!("{} group(s) dissolved.", count)); + self.command_line + .push_info(&format!("{} group(s) dissolved.", count)); } else { - self.command_line.push_info("No groups found for selected objects."); + self.command_line + .push_info("No groups found for selected objects."); } } - CmdResult::VpLayerUpdate { vp_handle, freeze, thaw } => { + CmdResult::VpLayerUpdate { + vp_handle, + freeze, + thaw, + } => { // Resolve layer names → handles, then update frozen_layers on the viewport(s). // vp_handle == Handle::NULL means "apply to all viewports in current layout". - let freeze_handles: Vec = freeze.iter() + let freeze_handles: Vec = freeze + .iter() .filter_map(|name| { - self.tabs[i].scene.document.layers.iter() + self.tabs[i] + .scene + .document + .layers + .iter() .find(|l| l.name.eq_ignore_ascii_case(name)) .map(|l| l.handle) }) .collect(); - let thaw_handles: Vec = thaw.iter() + let thaw_handles: Vec = thaw + .iter() .filter_map(|name| { - self.tabs[i].scene.document.layers.iter() + self.tabs[i] + .scene + .document + .layers + .iter() .find(|l| l.name.eq_ignore_ascii_case(name)) .map(|l| l.handle) }) @@ -505,7 +556,10 @@ impl H7CAD { let target_handles: Vec = if vp_handle == acadrust::Handle::NULL { // All viewports in current layout block let block_handle = self.tabs[i].scene.current_layout_block_handle_pub(); - self.tabs[i].scene.document.entities() + self.tabs[i] + .scene + .document + .entities() .filter(|e| { e.common().owner_handle == block_handle && matches!(e, acadrust::EntityType::Viewport(_)) @@ -529,7 +583,9 @@ impl H7CAD { for h in &thaw_handles { let before = vp.frozen_layers.len(); vp.frozen_layers.retain(|fh| fh != h); - if vp.frozen_layers.len() < before { thawed_count += 1; } + if vp.frozen_layers.len() < before { + thawed_count += 1; + } } } } @@ -538,15 +594,21 @@ impl H7CAD { self.push_undo_snapshot(i, "VPLAYER"); self.tabs[i].dirty = true; if frozen_count > 0 { - self.command_line.push_info(&format!("VPLAYER: {frozen_count} layer(s) frozen in viewport.")); + self.command_line.push_info(&format!( + "VPLAYER: {frozen_count} layer(s) frozen in viewport." + )); } if thawed_count > 0 { - self.command_line.push_info(&format!("VPLAYER: {thawed_count} layer(s) thawed in viewport.")); + self.command_line.push_info(&format!( + "VPLAYER: {thawed_count} layer(s) thawed in viewport." + )); } // Sync layer panel so VP freeze columns update immediately. let doc_layers = self.tabs[i].scene.document.layers.clone(); let vp_info = self.tabs[i].scene.viewport_list(); - self.tabs[i].layers.sync_with_viewports(&doc_layers, vp_info); + self.tabs[i] + .layers + .sync_with_viewports(&doc_layers, vp_info); } // Show updated prompt (command stays active for more operations). @@ -570,7 +632,13 @@ impl H7CAD { self.restore_pre_cmd_tangent(); self.command_line.push_output(&msg); } - CmdResult::AlignSelected { handles, src1, dst1, angle_rad, scale } => { + CmdResult::AlignSelected { + handles, + src1, + dst1, + angle_rad, + scale, + } => { if handles.is_empty() { self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; @@ -622,9 +690,15 @@ impl H7CAD { self.refresh_properties(); } } - CmdResult::LengthenEntity { handle, pick_pt, mode } => { + CmdResult::LengthenEntity { + handle, + pick_pt, + mode, + } => { use crate::modules::home::modify::lengthen::lengthen_entity; - let result = self.tabs[i].scene.document + let result = self.tabs[i] + .scene + .document .get_entity(handle) .and_then(|e| lengthen_entity(e, pick_pt, &mode)); match result { @@ -638,7 +712,8 @@ impl H7CAD { self.refresh_properties(); } None => { - self.command_line.push_error("LENGTHEN: entity type not supported."); + self.command_line + .push_error("LENGTHEN: entity type not supported."); } } self.tabs[i].active_cmd = None; @@ -648,38 +723,53 @@ impl H7CAD { } CmdResult::DivideEntity { handle, n } => { use crate::modules::home::inquiry::divide::divide_entity; - let pts = self.tabs[i].scene.document + let pts = self.tabs[i] + .scene + .document .get_entity(handle) .map(|e| divide_entity(e, n)) .unwrap_or_default(); let count = pts.len(); if count > 0 { self.push_undo_snapshot(i, "DIVIDE"); - for p in pts { self.tabs[i].scene.add_entity(p); } + for p in pts { + self.tabs[i].scene.add_entity(p); + } self.tabs[i].dirty = true; - self.command_line.push_output(&format!("DIVIDE: {count} point(s) placed.")); + self.command_line + .push_output(&format!("DIVIDE: {count} point(s) placed.")); } else { - self.command_line.push_error("DIVIDE: entity type not supported or N < 2."); + self.command_line + .push_error("DIVIDE: entity type not supported or N < 2."); } self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; self.tabs[i].scene.clear_preview_wire(); self.restore_pre_cmd_tangent(); } - CmdResult::MeasureEntity { handle, segment_length } => { + CmdResult::MeasureEntity { + handle, + segment_length, + } => { use crate::modules::home::inquiry::divide::measure_entity; - let pts = self.tabs[i].scene.document + let pts = self.tabs[i] + .scene + .document .get_entity(handle) .map(|e| measure_entity(e, segment_length)) .unwrap_or_default(); let count = pts.len(); if count > 0 { self.push_undo_snapshot(i, "MEASURE"); - for p in pts { self.tabs[i].scene.add_entity(p); } + for p in pts { + self.tabs[i].scene.add_entity(p); + } self.tabs[i].dirty = true; - self.command_line.push_output(&format!("MEASURE: {count} point(s) placed.")); + self.command_line + .push_output(&format!("MEASURE: {count} point(s) placed.")); } else { - self.command_line.push_error("MEASURE: entity type not supported or distance too large."); + self.command_line + .push_error("MEASURE: entity type not supported or distance too large."); } self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; @@ -688,7 +778,9 @@ impl H7CAD { } CmdResult::PeditOp { handle, op } => { use crate::modules::home::modify::pedit::apply_pedit; - let changed = self.tabs[i].scene.document + let changed = self.tabs[i] + .scene + .document .get_entity_mut(handle) .map(|e| apply_pedit(e, &op)) .unwrap_or(false); @@ -698,16 +790,17 @@ impl H7CAD { self.command_line.push_output("PEDIT: applied."); self.refresh_properties(); } else { - self.command_line.push_error("PEDIT: operation not applicable to this entity."); + self.command_line + .push_error("PEDIT: operation not applicable to this entity."); } // Keep command active — user may apply more ops - self.command_line.push_info( - "PEDIT Enter option [C=Close O=Open W=Width X=Exit]:" - ); + self.command_line + .push_info("PEDIT Enter option [C=Close O=Open W=Width X=Exit]:"); } CmdResult::JoinEntities(handles) => { use crate::modules::home::modify::join::join_entities; - let pairs: Vec<_> = handles.iter() + let pairs: Vec<_> = handles + .iter() .filter_map(|&h| self.tabs[i].scene.document.get_entity(h).map(|e| (h, e))) .collect(); match join_entities(&pairs) { @@ -725,9 +818,9 @@ impl H7CAD { self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; self.restore_pre_cmd_tangent(); - self.command_line.push_output( - &format!("JOIN: {count_in} object(s) joined into {count_out}.") - ); + self.command_line.push_output(&format!( + "JOIN: {count_in} object(s) joined into {count_out}." + )); self.refresh_properties(); } None => { @@ -736,14 +829,16 @@ impl H7CAD { self.tabs[i].scene.clear_preview_wire(); self.restore_pre_cmd_tangent(); self.command_line.push_error( - "JOIN: objects are not collinear/co-circular or have gaps." + "JOIN: objects are not collinear/co-circular or have gaps.", ); } } } CmdResult::BreakEntity { handle, p1, p2 } => { use crate::modules::home::modify::break_cmd::break_entity; - let replacement = self.tabs[i].scene.document + let replacement = self.tabs[i] + .scene + .document .get_entity(handle) .and_then(|e| break_entity(e, p1, p2)); match replacement { @@ -760,7 +855,8 @@ impl H7CAD { self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; self.restore_pre_cmd_tangent(); - self.command_line.push_output(&format!("BREAK: {} fragment(s).", count)); + self.command_line + .push_output(&format!("BREAK: {} fragment(s).", count)); self.refresh_properties(); } None => { @@ -768,7 +864,8 @@ impl H7CAD { self.tabs[i].snap_result = None; self.tabs[i].scene.clear_preview_wire(); self.restore_pre_cmd_tangent(); - self.command_line.push_error("BREAK: entity type not supported."); + self.command_line + .push_error("BREAK: entity type not supported."); } } } @@ -776,14 +873,21 @@ impl H7CAD { use acadrust::objects::{ObjectType, PlotSettings}; let layout_name = self.tabs[i].scene.current_layout.clone(); if layout_name == "Model" { - self.command_line.push_error("PLOTWINDOW: switch to a paper space layout first."); + self.command_line + .push_error("PLOTWINDOW: switch to a paper space layout first."); } else { let block_handle = self.tabs[i].scene.current_layout_block_handle_pub(); let doc = &mut self.tabs[i].scene.document; let ps_handle = doc.objects.iter().find_map(|(h, obj)| { if let ObjectType::PlotSettings(ps) = obj { - if ps.page_name == layout_name { Some(*h) } else { None } - } else { None } + if ps.page_name == layout_name { + Some(*h) + } else { + None + } + } else { + None + } }); let ps_entry = match ps_handle { Some(h) => doc.objects.get_mut(&h), @@ -814,7 +918,12 @@ impl H7CAD { self.tabs[i].scene.clear_preview_wire(); self.restore_pre_cmd_tangent(); } - CmdResult::StretchEntities { handles, win_min, win_max, delta } => { + CmdResult::StretchEntities { + handles, + win_min, + win_max, + delta, + } => { self.push_undo_snapshot(i, "STRETCH"); let mut count = 0usize; @@ -823,8 +932,7 @@ impl H7CAD { let in_win = |x: f64, y: f64| -> bool { let wx = x as f32; let wy = y as f32; - wx >= win_min.x && wx <= win_max.x - && wy >= win_min.z && wy <= win_max.z + wx >= win_min.x && wx <= win_max.x && wy >= win_min.z && wy <= win_max.z }; let dx = delta.x as f64; @@ -832,14 +940,26 @@ impl H7CAD { let dz = delta.y as f64; for handle in &handles { - let Some(entity) = self.tabs[i].scene.document.get_entity_mut(*handle) else { continue }; + let Some(entity) = self.tabs[i].scene.document.get_entity_mut(*handle) else { + continue; + }; let mut stretched = false; match entity { acadrust::EntityType::Line(l) => { let s_in = in_win(l.start.x, l.start.y); let e_in = in_win(l.end.x, l.end.y); - if s_in { l.start.x += dx; l.start.y += dy; l.start.z += dz; stretched = true; } - if e_in { l.end.x += dx; l.end.y += dy; l.end.z += dz; stretched = true; } + if s_in { + l.start.x += dx; + l.start.y += dy; + l.start.z += dz; + stretched = true; + } + if e_in { + l.end.x += dx; + l.end.y += dy; + l.end.z += dz; + stretched = true; + } } acadrust::EntityType::LwPolyline(p) => { for v in &mut p.vertices { @@ -870,37 +990,49 @@ impl H7CAD { } acadrust::EntityType::Arc(a) => { if in_win(a.center.x, a.center.y) { - a.center.x += dx; a.center.y += dy; a.center.z += dz; + a.center.x += dx; + a.center.y += dy; + a.center.z += dz; stretched = true; } } acadrust::EntityType::Circle(c) => { if in_win(c.center.x, c.center.y) { - c.center.x += dx; c.center.y += dy; c.center.z += dz; + c.center.x += dx; + c.center.y += dy; + c.center.z += dz; stretched = true; } } acadrust::EntityType::Ellipse(e) => { if in_win(e.center.x, e.center.y) { - e.center.x += dx; e.center.y += dy; e.center.z += dz; + e.center.x += dx; + e.center.y += dy; + e.center.z += dz; stretched = true; } } acadrust::EntityType::Insert(ins) => { if in_win(ins.insert_point.x, ins.insert_point.y) { - ins.insert_point.x += dx; ins.insert_point.y += dy; ins.insert_point.z += dz; + ins.insert_point.x += dx; + ins.insert_point.y += dy; + ins.insert_point.z += dz; stretched = true; } } acadrust::EntityType::Text(t) => { if in_win(t.insertion_point.x, t.insertion_point.y) { - t.insertion_point.x += dx; t.insertion_point.y += dy; t.insertion_point.z += dz; + t.insertion_point.x += dx; + t.insertion_point.y += dy; + t.insertion_point.z += dz; stretched = true; } } acadrust::EntityType::MText(t) => { if in_win(t.insertion_point.x, t.insertion_point.y) { - t.insertion_point.x += dx; t.insertion_point.y += dy; t.insertion_point.z += dz; + t.insertion_point.x += dx; + t.insertion_point.y += dy; + t.insertion_point.z += dz; stretched = true; } } @@ -909,7 +1041,9 @@ impl H7CAD { stretched = false; // skip generic types } } - if stretched { count += 1; } + if stretched { + count += 1; + } } self.tabs[i].dirty = true; @@ -917,7 +1051,8 @@ impl H7CAD { self.tabs[i].snap_result = None; self.tabs[i].scene.clear_preview_wire(); self.restore_pre_cmd_tangent(); - self.command_line.push_output(&format!("STRETCH: {count} entity(ies) stretched.")); + self.command_line + .push_output(&format!("STRETCH: {count} entity(ies) stretched.")); self.refresh_properties(); } // ── Solid3D creation (BOX / SPHERE / CYLINDER) ──────────────── @@ -943,11 +1078,15 @@ impl H7CAD { } // ── EXTRUDE ──────────────────────────────────────────────────── - CmdResult::ExtrudeEntity { handle, height, color } => { + CmdResult::ExtrudeEntity { + handle, + height, + color, + } => { use crate::entities::traits::EntityTypeOps; + use crate::modules::insert::solid3d_cmds::empty_solid3d; use crate::scene::acad_to_truck::TruckObject; use crate::scene::truck_tess; - use crate::modules::insert::solid3d_cmds::empty_solid3d; use truck_modeling::builder; use truck_modeling::Vector3 as TruckVec3; @@ -961,16 +1100,21 @@ impl H7CAD { // Attach a planar face to the wire profile, then sweep. let face = builder::try_attach_plane(&[wire]).ok()?; // tsweep(Face) → Solid - let solid = builder::tsweep(&face, TruckVec3::new(0.0, 0.0, height as f64)); + let solid = + builder::tsweep(&face, TruckVec3::new(0.0, 0.0, height as f64)); match truck_tess::tessellate_solid(&solid, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => { - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), - verts, normals, indices, - color, - selected: false, - }) - } + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } } @@ -998,11 +1142,17 @@ impl H7CAD { } // ── REVOLVE ──────────────────────────────────────────────────── - CmdResult::RevolveEntity { handle, axis_start, axis_end, angle_deg, color } => { + CmdResult::RevolveEntity { + handle, + axis_start, + axis_end, + angle_deg, + color, + } => { use crate::entities::traits::EntityTypeOps; + use crate::modules::insert::solid3d_cmds::empty_solid3d; use crate::scene::acad_to_truck::TruckObject; use crate::scene::truck_tess; - use crate::modules::insert::solid3d_cmds::empty_solid3d; use truck_modeling::builder; use truck_modeling::{Point3, Rad, Vector3 as TruckVec3}; @@ -1024,16 +1174,25 @@ impl H7CAD { ); let dir = (axis_end - axis_start).normalize(); let axis = TruckVec3::new(dir.x as f64, dir.z as f64, dir.y as f64); - let shell = builder::rsweep(&wire, origin, axis, Rad(angle_deg.to_radians() as f64)); + let shell = builder::rsweep( + &wire, + origin, + axis, + Rad(angle_deg.to_radians() as f64), + ); match truck_tess::tessellate_shell(&shell, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => { - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), - verts, normals, indices, - color, - selected: false, - }) - } + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } }); @@ -1044,9 +1203,11 @@ impl H7CAD { mesh.name = format!("{}", new_handle.value()); self.tabs[i].scene.meshes.insert(new_handle, mesh); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("REVOLVE: solid created ({:.0}°).", angle_deg)); + self.command_line + .push_output(&format!("REVOLVE: solid created ({:.0}°).", angle_deg)); } else { - self.command_line.push_error("REVOLVE: could not revolve profile."); + self.command_line + .push_error("REVOLVE: could not revolve profile."); } } else { self.command_line.push_error("REVOLVE: entity not found."); @@ -1058,16 +1219,24 @@ impl H7CAD { } // ── SWEEP ────────────────────────────────────────────────────── - CmdResult::SweepEntity { profile_handle, path_handle, color } => { + CmdResult::SweepEntity { + profile_handle, + path_handle, + color, + } => { use crate::entities::traits::EntityTypeOps; + use crate::modules::insert::solid3d_cmds::empty_solid3d; use crate::scene::acad_to_truck::TruckObject; use crate::scene::truck_tess; - use crate::modules::insert::solid3d_cmds::empty_solid3d; use truck_modeling::builder; use truck_modeling::Vector3 as TruckVec3; - let profile_ent = self.tabs[i].scene.document.get_entity(profile_handle).cloned(); - let path_ent = self.tabs[i].scene.document.get_entity(path_handle).cloned(); + let profile_ent = self.tabs[i] + .scene + .document + .get_entity(profile_handle) + .cloned(); + let path_ent = self.tabs[i].scene.document.get_entity(path_handle).cloned(); let woff = self.tabs[i].scene.world_offset; let result = profile_ent.zip(path_ent).and_then(|(prof_e, path_e)| { @@ -1077,7 +1246,7 @@ impl H7CAD { // Profile must be a wire (closed or open). let profile_wire: truck_modeling::Wire = match prof_truck.object { TruckObject::Contour(w) => w, - TruckObject::Curve(e) => std::iter::once(e).collect(), + TruckObject::Curve(e) => std::iter::once(e).collect(), _ => return None, }; @@ -1086,7 +1255,7 @@ impl H7CAD { // Linear path: translate profile along the line direction. TruckObject::Curve(edge) => { let p_start = edge.front().point(); - let p_end = edge.back().point(); + let p_end = edge.back().point(); let dir = TruckVec3::new( p_end.x - p_start.x, p_end.y - p_start.y, @@ -1097,19 +1266,35 @@ impl H7CAD { if let Ok(face) = builder::try_attach_plane(&[profile_wire.clone()]) { let solid = builder::tsweep(&face, dir); match truck_tess::tessellate_solid(&solid, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), verts, normals, indices, color, selected: false, - }), + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } } else { let shell = builder::tsweep(&profile_wire, dir); match truck_tess::tessellate_shell(&shell, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), verts, normals, indices, color, selected: false, - }), + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } } @@ -1121,7 +1306,7 @@ impl H7CAD { TruckObject::Contour(path_wire) => { // Use start→end of the whole wire as translation vector. let p_start = path_wire.front_vertex()?.point(); - let p_end = path_wire.back_vertex()?.point(); + let p_end = path_wire.back_vertex()?.point(); let dir = TruckVec3::new( p_end.x - p_start.x, p_end.y - p_start.y, @@ -1130,19 +1315,35 @@ impl H7CAD { if let Ok(face) = builder::try_attach_plane(&[profile_wire.clone()]) { let solid = builder::tsweep(&face, dir); match truck_tess::tessellate_solid(&solid, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), verts, normals, indices, color, selected: false, - }), + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } } else { let shell = builder::tsweep(&profile_wire, dir); match truck_tess::tessellate_shell(&shell, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), verts, normals, indices, color, selected: false, - }), + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } } @@ -1173,9 +1374,9 @@ impl H7CAD { // ── LOFT ─────────────────────────────────────────────────────── CmdResult::LoftEntities { handles, color } => { use crate::entities::traits::EntityTypeOps; + use crate::modules::insert::solid3d_cmds::empty_solid3d; use crate::scene::acad_to_truck::TruckObject; use crate::scene::truck_tess; - use crate::modules::insert::solid3d_cmds::empty_solid3d; use truck_modeling::builder; // Collect wires from each profile. @@ -1185,24 +1386,30 @@ impl H7CAD { if let Some(te) = ent.to_truck_entity(&self.tabs[i].scene.document) { let wire = match te.object { TruckObject::Contour(w) => Some(w), - TruckObject::Curve(e) => Some(std::iter::once(e).collect()), + TruckObject::Curve(e) => Some(std::iter::once(e).collect()), _ => None, }; - if let Some(w) = wire { wires.push(w); } + if let Some(w) = wire { + wires.push(w); + } } } } let woff = self.tabs[i].scene.world_offset; let result: Option = (|| { - if wires.len() < 2 { return None; } + if wires.len() < 2 { + return None; + } // Build ruled shells between consecutive profile pairs. let mut all_faces: Vec = Vec::new(); for pair in wires.windows(2) { let shell = builder::try_wire_homotopy(&pair[0], &pair[1]).ok()?; - for face in shell.into_iter() { all_faces.push(face); } + for face in shell.into_iter() { + all_faces.push(face); + } } // Cap the first and last profiles if they are closed. @@ -1215,10 +1422,18 @@ impl H7CAD { let shell = truck_modeling::Shell::from(all_faces); match truck_tess::tessellate_shell(&shell, woff) { - truck_tess::TruckTessResult::Mesh { verts, normals, indices } => - Some(crate::scene::mesh_model::MeshModel { - name: String::new(), verts, normals, indices, color, selected: false, - }), + truck_tess::TruckTessResult::Mesh { + verts, + normals, + indices, + } => Some(crate::scene::mesh_model::MeshModel { + name: String::new(), + verts, + normals, + indices, + color, + selected: false, + }), _ => None, } })(); @@ -1230,7 +1445,10 @@ impl H7CAD { mesh.name = format!("{}", new_handle.value()); self.tabs[i].scene.meshes.insert(new_handle, mesh); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("LOFT: solid created from {} profiles.", handles.len())); + self.command_line.push_output(&format!( + "LOFT: solid created from {} profiles.", + handles.len() + )); } else { self.command_line.push_error("LOFT: could not loft profiles. Ensure sections have the same edge count and are compatible."); } @@ -1240,7 +1458,12 @@ impl H7CAD { self.restore_pre_cmd_tangent(); } - CmdResult::HatcheditApply { handle, name, scale, angle } => { + CmdResult::HatcheditApply { + handle, + name, + scale, + angle, + } => { if let Some(mut model) = self.tabs[i].scene.hatches.get(&handle).cloned() { // Update model fields if !name.is_empty() { @@ -1265,7 +1488,8 @@ impl H7CAD { self.tabs[i].dirty = true; self.command_line.push_output("HATCHEDIT: hatch updated."); } else { - self.command_line.push_error("HATCHEDIT: hatch entity not found."); + self.command_line + .push_error("HATCHEDIT: hatch entity not found."); } self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; @@ -1276,10 +1500,22 @@ impl H7CAD { let mut updated = false; if let Some(entity) = self.tabs[i].scene.document.get_entity_mut(handle) { match entity { - acadrust::EntityType::Text(t) => { t.value = new_text; updated = true; } - acadrust::EntityType::MText(t) => { t.value = new_text; updated = true; } - acadrust::EntityType::AttributeDefinition(a) => { a.default_value = new_text; updated = true; } - acadrust::EntityType::AttributeEntity(a) => { a.set_value(new_text); updated = true; } + acadrust::EntityType::Text(t) => { + t.value = new_text; + updated = true; + } + acadrust::EntityType::MText(t) => { + t.value = new_text; + updated = true; + } + acadrust::EntityType::AttributeDefinition(a) => { + a.default_value = new_text; + updated = true; + } + acadrust::EntityType::AttributeEntity(a) => { + a.set_value(new_text); + updated = true; + } acadrust::EntityType::Dimension(d) => { // Empty string resets to auto-measured value; otherwise set override. let base = d.base_mut(); @@ -1294,7 +1530,8 @@ impl H7CAD { self.tabs[i].dirty = true; self.command_line.push_output("DDEDIT: text updated."); } else { - self.command_line.push_error("DDEDIT: entity type not supported."); + self.command_line + .push_error("DDEDIT: entity type not supported."); } self.tabs[i].active_cmd = None; self.tabs[i].snap_result = None; @@ -1327,17 +1564,19 @@ impl H7CAD { fn apply_dimspace(scene: &mut crate::scene::Scene, encoded: &str) { // Format: ",

;

;...;," let parts: Vec<&str> = encoded.splitn(3, ',').collect(); - if parts.len() < 3 { return; } + if parts.len() < 3 { + return; + } let base_val: u64 = parts[0].parse().unwrap_or(0); - let other_vals: Vec = parts[1].split(';') + let other_vals: Vec = parts[1] + .split(';') .filter_map(|s| s.parse::().ok()) .collect(); let spacing: f64 = parts[2].parse().unwrap_or(0.0); let base_h = acadrust::Handle::from(base_val); // Read base dimension's definition_point Z (perpendicular offset) - let base_z = if let Some(acadrust::EntityType::Dimension(d)) = - scene.document.get_entity(base_h) + let base_z = if let Some(acadrust::EntityType::Dimension(d)) = scene.document.get_entity(base_h) { d.base().definition_point.z } else { @@ -1361,17 +1600,18 @@ fn apply_dimspace(scene: &mut crate::scene::Scene, encoded: &str) { fn apply_mleader_align(scene: &mut crate::scene::Scene, encoded: &str) { // Format: "

,

,...;,;," let parts: Vec<&str> = encoded.splitn(3, ';').collect(); - if parts.len() < 3 { return; } - let handles: Vec = parts[0].split(',') + if parts.len() < 3 { + return; + } + let handles: Vec = parts[0] + .split(',') .filter_map(|s| s.parse::().ok().map(acadrust::Handle::from)) .collect(); - let from_parts: Vec = parts[1].split(',') - .filter_map(|s| s.parse().ok()) - .collect(); - let to_parts: Vec = parts[2].split(',') - .filter_map(|s| s.parse().ok()) - .collect(); - if from_parts.len() < 2 || to_parts.len() < 2 || handles.is_empty() { return; } + let from_parts: Vec = parts[1].split(',').filter_map(|s| s.parse().ok()).collect(); + let to_parts: Vec = parts[2].split(',').filter_map(|s| s.parse().ok()).collect(); + if from_parts.len() < 2 || to_parts.len() < 2 || handles.is_empty() { + return; + } let fx = from_parts[0]; let fz = from_parts[1]; @@ -1380,7 +1620,9 @@ fn apply_mleader_align(scene: &mut crate::scene::Scene, encoded: &str) { let dx = tx - fx; let dz = tz - fz; let len = (dx * dx + dz * dz).sqrt(); - if len < 1e-9 { return; } + if len < 1e-9 { + return; + } // Project each multileader's content point onto the alignment line, then // snap it to the line (preserve perpendicular offset from line is discarded; @@ -1404,14 +1646,17 @@ fn apply_mleader_align(scene: &mut crate::scene::Scene, encoded: &str) { /// Parse `h1,h2,...;px,pz` — merge all selected multileaders into the first one at position. fn apply_mleader_collect(scene: &mut crate::scene::Scene, encoded: &str) { let parts: Vec<&str> = encoded.splitn(2, ';').collect(); - if parts.len() < 2 { return; } - let handles: Vec = parts[0].split(',') + if parts.len() < 2 { + return; + } + let handles: Vec = parts[0] + .split(',') .filter_map(|s| s.parse::().ok().map(acadrust::Handle::from)) .collect(); - let pos_parts: Vec = parts[1].split(',') - .filter_map(|s| s.parse().ok()) - .collect(); - if handles.len() < 2 || pos_parts.len() < 2 { return; } + let pos_parts: Vec = parts[1].split(',').filter_map(|s| s.parse().ok()).collect(); + if handles.len() < 2 || pos_parts.len() < 2 { + return; + } let px = pos_parts[0]; let pz = pos_parts[1]; diff --git a/src/app/commands.rs b/src/app/commands.rs index a83fe64d8..b341e0f12 100644 --- a/src/app/commands.rs +++ b/src/app/commands.rs @@ -1,4 +1,4 @@ -use super::{H7CAD, Message}; +use super::{Message, H7CAD}; use crate::command::CadCommand; use crate::scene::Scene; use iced::Task; @@ -22,15 +22,15 @@ impl H7CAD { } match cmd { - "NEW" => return Task::done(Message::TabNew), - "OPEN" => return Task::done(Message::OpenFile), - "SAVE"|"QSAVE" => return Task::done(Message::SaveFile), - "SAVEAS" => return Task::done(Message::SaveAs), - "UNDO"|"U" => return Task::done(Message::Undo), - "REDO" => return Task::done(Message::Redo), - "CLEAR"|"CLR" => return Task::done(Message::ClearScene), - "WIREFRAME"|"VW" => return Task::done(Message::SetWireframe(true)), - "SOLID"|"VS" => return Task::done(Message::SetWireframe(false)), + "NEW" => return Task::done(Message::TabNew), + "OPEN" => return Task::done(Message::OpenFile), + "SAVE" | "QSAVE" => return Task::done(Message::SaveFile), + "SAVEAS" => return Task::done(Message::SaveAs), + "UNDO" | "U" => return Task::done(Message::Undo), + "REDO" => return Task::done(Message::Redo), + "CLEAR" | "CLR" => return Task::done(Message::ClearScene), + "WIREFRAME" | "VW" => return Task::done(Message::SetWireframe(true)), + "SOLID" | "VS" => return Task::done(Message::SetWireframe(false)), // ── Background color ─────────────────────────────────────────── // Usage: BACKGROUND (0–255 each) @@ -38,7 +38,11 @@ impl H7CAD { cmd if cmd == "BACKGROUND" || cmd.starts_with("BACKGROUND ") => { let args = cmd.split_whitespace().skip(1).collect::>(); let is_paper = self.tabs[i].scene.current_layout != "Model"; - if args.first().map(|s| s.eq_ignore_ascii_case("RESET")).unwrap_or(false) { + if args + .first() + .map(|s| s.eq_ignore_ascii_case("RESET")) + .unwrap_or(false) + { if is_paper { self.tabs[i].paper_bg_color = None; self.tabs[i].scene.paper_bg_color = [1.0, 1.0, 1.0, 1.0]; @@ -46,7 +50,8 @@ impl H7CAD { self.tabs[i].bg_color = None; self.tabs[i].scene.bg_color = [0.11, 0.11, 0.11, 1.0]; } - self.command_line.push_output("Background reset to default."); + self.command_line + .push_output("Background reset to default."); } else if args.len() >= 3 { let r = args[0].parse::().unwrap_or(0) as f32 / 255.0; let g = args[1].parse::().unwrap_or(0) as f32 / 255.0; @@ -58,34 +63,44 @@ impl H7CAD { self.tabs[i].bg_color = Some([r, g, b, 1.0]); self.tabs[i].scene.bg_color = [r, g, b, 1.0]; } - self.command_line - .push_output(&format!("Background: rgb({}, {}, {})", args[0], args[1], args[2])); + self.command_line.push_output(&format!( + "Background: rgb({}, {}, {})", + args[0], args[1], args[2] + )); } else { - self.command_line.push_info( - "Usage: BACKGROUND (0–255) | BACKGROUND RESET" - ); + self.command_line + .push_info("Usage: BACKGROUND (0–255) | BACKGROUND RESET"); } } - "ORTHO" => return Task::done(Message::SetProjection(true)), - "PERSP" => return Task::done(Message::SetProjection(false)), - "LAYERS"|"LA" => return Task::done(Message::ToggleLayers), + "ORTHO" => return Task::done(Message::SetProjection(true)), + "PERSP" => return Task::done(Message::SetProjection(false)), + "LAYERS" | "LA" => return Task::done(Message::ToggleLayers), // ── Layer object commands ────────────────────────────────────── "LAYOFF" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("LAYOFF"); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - let layers: std::collections::HashSet = self.tabs[i].scene - .selected_entities().into_iter() - .map(|(_, e)| e.common().layer.clone()).collect(); + let layers: std::collections::HashSet = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(_, e)| e.common().layer.clone()) + .collect(); self.push_undo_snapshot(i, "LAYOFF"); for name in &layers { - if name == "0" { continue; } + if name == "0" { + continue; + } if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(name) { dl.turn_off(); } @@ -97,20 +112,29 @@ impl H7CAD { } "LAYFRZ" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("LAYFRZ"); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - let layers: std::collections::HashSet = self.tabs[i].scene - .selected_entities().into_iter() - .map(|(_, e)| e.common().layer.clone()).collect(); + let layers: std::collections::HashSet = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(_, e)| e.common().layer.clone()) + .collect(); self.push_undo_snapshot(i, "LAYFRZ"); for name in &layers { - if name == "0" { continue; } + if name == "0" { + continue; + } if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(name) { dl.freeze(); } @@ -122,17 +146,24 @@ impl H7CAD { } "LAYLCK" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("LAYLCK"); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - let layers: std::collections::HashSet = self.tabs[i].scene - .selected_entities().into_iter() - .map(|(_, e)| e.common().layer.clone()).collect(); + let layers: std::collections::HashSet = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(_, e)| e.common().layer.clone()) + .collect(); self.push_undo_snapshot(i, "LAYLCK"); for name in &layers { if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(name) { @@ -157,15 +188,21 @@ impl H7CAD { self.tabs[i].active_layer = layer.clone(); self.ribbon.active_layer = layer.clone(); self.tabs[i].layers.current_layer = layer.clone(); - self.command_line.push_info(&format!("Current layer set to \"{layer}\".")); + self.command_line + .push_info(&format!("Current layer set to \"{layer}\".")); self.sync_ribbon_layers(); } } "LAYON" => { self.push_undo_snapshot(i, "LAYON"); - for name in self.tabs[i].scene.document.layers.iter() - .map(|l| l.name.clone()).collect::>() + for name in self.tabs[i] + .scene + .document + .layers + .iter() + .map(|l| l.name.clone()) + .collect::>() { if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(&name) { dl.turn_on(); @@ -178,8 +215,13 @@ impl H7CAD { "LAYTHW" => { self.push_undo_snapshot(i, "LAYTHW"); - for name in self.tabs[i].scene.document.layers.iter() - .map(|l| l.name.clone()).collect::>() + for name in self.tabs[i] + .scene + .document + .layers + .iter() + .map(|l| l.name.clone()) + .collect::>() { if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(&name) { dl.thaw(); @@ -191,17 +233,24 @@ impl H7CAD { } "LAYULK" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("LAYULK"); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - let layers: std::collections::HashSet = self.tabs[i].scene - .selected_entities().into_iter() - .map(|(_, e)| e.common().layer.clone()).collect(); + let layers: std::collections::HashSet = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(_, e)| e.common().layer.clone()) + .collect(); self.push_undo_snapshot(i, "LAYULK"); for name in &layers { if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(name) { @@ -216,15 +265,24 @@ impl H7CAD { // LAYISO — turn off all layers except those used by selected entities "LAYISO" => { - let sel_layers: std::collections::HashSet = self.tabs[i].scene - .selected_entities().into_iter() - .map(|(_, e)| e.common().layer.clone()).collect(); + let sel_layers: std::collections::HashSet = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(_, e)| e.common().layer.clone()) + .collect(); if sel_layers.is_empty() { - self.command_line.push_error("LAYISO: select entities on the layers to isolate first."); + self.command_line + .push_error("LAYISO: select entities on the layers to isolate first."); } else { self.push_undo_snapshot(i, "LAYISO"); - let names: Vec = self.tabs[i].scene.document.layers - .iter().map(|l| l.name.clone()).collect(); + let names: Vec = self.tabs[i] + .scene + .document + .layers + .iter() + .map(|l| l.name.clone()) + .collect(); for name in names { if !sel_layers.contains(&name) { if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(&name) { @@ -234,17 +292,21 @@ impl H7CAD { } self.tabs[i].dirty = true; self.sync_ribbon_layers(); - self.command_line.push_info(&format!( - "LAYISO: isolated {} layer(s).", sel_layers.len() - )); + self.command_line + .push_info(&format!("LAYISO: isolated {} layer(s).", sel_layers.len())); } } // LAYUNISO — restore all layers that were turned off by LAYISO (turn all on) "LAYUNISO" => { self.push_undo_snapshot(i, "LAYUNISO"); - let names: Vec = self.tabs[i].scene.document.layers - .iter().map(|l| l.name.clone()).collect(); + let names: Vec = self.tabs[i] + .scene + .document + .layers + .iter() + .map(|l| l.name.clone()) + .collect(); for name in names { if let Some(dl) = self.tabs[i].scene.document.layers.get_mut(&name) { dl.turn_on(); @@ -252,19 +314,24 @@ impl H7CAD { } self.tabs[i].dirty = true; self.sync_ribbon_layers(); - self.command_line.push_info("LAYUNISO: all layers restored."); + self.command_line + .push_info("LAYUNISO: all layers restored."); } - "LAYMATCH"|"LAYMCH" => { + "LAYMATCH" | "LAYMCH" => { use crate::modules::home::layers::match_layer::LayMatchCommand; - let dest: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let dest: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); let cmd = LayMatchCommand::new(dest); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "MATCHPROP"|"MA" => { + "MATCHPROP" | "MA" => { use crate::modules::home::properties::match_prop::MatchPropCommand; self.tabs[i].scene.deselect_all(); let cmd = MatchPropCommand::new(); @@ -272,9 +339,13 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "GROUP"|"G" => { + "GROUP" | "G" => { let handles: Vec<_> = self.tabs[i] - .scene.selected_entities().into_iter().map(|(h, _)| h).collect(); + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("GROUP"); @@ -289,9 +360,13 @@ impl H7CAD { } } - "UNGROUP"|"UG" => { + "UNGROUP" | "UG" => { let handles: Vec<_> = self.tabs[i] - .scene.selected_entities().into_iter().map(|(h, _)| h).collect(); + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::groups::ungroup::UngroupCommand; let cmd = UngroupCommand::new(); @@ -302,45 +377,58 @@ impl H7CAD { let count = self.tabs[i].scene.delete_groups_containing(&handles); self.tabs[i].dirty = true; if count > 0 { - self.command_line.push_info(&format!("{} group(s) dissolved.", count)); + self.command_line + .push_info(&format!("{} group(s) dissolved.", count)); } else { - self.command_line.push_info("No groups found for selected objects."); + self.command_line + .push_info("No groups found for selected objects."); } } } - "COPYCLIP"|"CC" => { + "COPYCLIP" | "CC" => { let handles: Vec<_> = self.tabs[i] - .scene.selected_entities().into_iter().map(|(h, _)| h).collect(); + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("COPYCLIP"); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - let entities: Vec<_> = handles.iter() + let entities: Vec<_> = handles + .iter() .filter_map(|&h| self.tabs[i].scene.document.get_entity(h).cloned()) .collect(); self.clipboard_centroid = super::helpers::entities_centroid( &self.tabs[i].scene.wire_models_for(&handles), ); self.clipboard = entities; - self.command_line.push_info( - &format!("{} object(s) copied to clipboard.", self.clipboard.len()), - ); + self.command_line.push_info(&format!( + "{} object(s) copied to clipboard.", + self.clipboard.len() + )); } } - "CUTCLIP"|"CX" => { + "CUTCLIP" | "CX" => { let handles: Vec<_> = self.tabs[i] - .scene.selected_entities().into_iter().map(|(h, _)| h).collect(); + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("CUTCLIP"); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - let entities: Vec<_> = handles.iter() + let entities: Vec<_> = handles + .iter() .filter_map(|&h| self.tabs[i].scene.document.get_entity(h).cloned()) .collect(); self.clipboard_centroid = super::helpers::entities_centroid( @@ -353,13 +441,12 @@ impl H7CAD { self.tabs[i].scene.deselect_all(); self.tabs[i].dirty = true; self.refresh_properties(); - self.command_line.push_info( - &format!("{} object(s) cut to clipboard.", count), - ); + self.command_line + .push_info(&format!("{} object(s) cut to clipboard.", count)); } } - "PASTECLIP"|"PC" => { + "PASTECLIP" | "PC" => { if self.clipboard.is_empty() { self.command_line.push_error("Clipboard is empty."); } else { @@ -374,7 +461,8 @@ impl H7CAD { // PASTEORIG — paste at original coordinates (no move to pick point) "PASTEORIG" => { if self.clipboard.is_empty() { - self.command_line.push_error("PASTEORIG: clipboard is empty."); + self.command_line + .push_error("PASTEORIG: clipboard is empty."); } else { let count = self.clipboard.len(); self.push_undo_snapshot(i, "PASTEORIG"); @@ -383,14 +471,19 @@ impl H7CAD { } self.tabs[i].dirty = true; self.command_line.push_output(&format!( - "PASTEORIG: {} object(s) pasted at original coordinates.", count + "PASTEORIG: {} object(s) pasted at original coordinates.", + count )); } } "BLOCK" => { let handles: Vec<_> = self.tabs[i] - .scene.selected_entities().into_iter().map(|(h, _)| h).collect(); + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("BLOCK"); @@ -460,7 +553,8 @@ impl H7CAD { }) .collect(); if xrefs.is_empty() { - self.command_line.push_output("XREF No external references in this drawing."); + self.command_line + .push_output("XREF No external references in this drawing."); } else { self.command_line.push_output("XREF External references:"); for line in xrefs { @@ -480,10 +574,8 @@ impl H7CAD { for info in &infos { match info.status { crate::io::xref::XrefStatus::Loaded => { - self.command_line.push_output(&format!( - "XREF Reloaded \"{}\"", - info.name - )); + self.command_line + .push_output(&format!("XREF Reloaded \"{}\"", info.name)); } crate::io::xref::XrefStatus::NotFound => { self.command_line.push_error(&format!( @@ -498,19 +590,20 @@ impl H7CAD { self.tabs[i].scene.populate_meshes_from_document(); } } else { - self.command_line.push_error("XREF Save the drawing first to resolve relative XREF paths."); + self.command_line + .push_error("XREF Save the drawing first to resolve relative XREF paths."); } } // ── Draw commands ────────────────────────────────────────────── - "LINE"|"L" => { + "LINE" | "L" => { use crate::modules::home::draw::line::LineCommand; let new_cmd = LineCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "MLINE"|"ML" => { + "MLINE" | "ML" => { use crate::modules::home::draw::mline::MlineCommand; let style = self.tabs[i].scene.document.header.multiline_style.clone(); let cmd_obj = MlineCommand::with_style(style); @@ -520,7 +613,10 @@ impl H7CAD { cmd if cmd == "WIPEOUT" || cmd == "WO" || cmd.starts_with("WIPEOUT ") => { use crate::modules::home::draw::wipeout::WipeoutCommand; - let args = cmd.split_once(' ').map(|(_, r)| r.trim().to_uppercase()).unwrap_or_default(); + let args = cmd + .split_once(' ') + .map(|(_, r)| r.trim().to_uppercase()) + .unwrap_or_default(); let wo_cmd = if args == "P" || args == "POLYGONAL" { WipeoutCommand::new_polygonal() } else { @@ -555,25 +651,31 @@ impl H7CAD { cmd if cmd == "ATTEDIT" || cmd.starts_with("ATTEDIT ") => { let rest = cmd.trim_start_matches("ATTEDIT").trim(); let parts: Vec<&str> = rest.splitn(2, char::is_whitespace).collect(); - let selected_handles: Vec = self.tabs[i].scene + let selected_handles: Vec = self.tabs[i] + .scene .selected_entities() .iter() .map(|(h, _)| *h) .collect(); if selected_handles.is_empty() { - self.command_line.push_error("ATTEDIT: select an Insert entity first."); + self.command_line + .push_error("ATTEDIT: select an Insert entity first."); } else { let mut found_any = false; for sh in &selected_handles { - if let Some(acadrust::EntityType::Insert(ins)) = - self.tabs[i].scene.document.entities().find(|e| e.common().handle == *sh) + if let Some(acadrust::EntityType::Insert(ins)) = self.tabs[i] + .scene + .document + .entities() + .find(|e| e.common().handle == *sh) { found_any = true; if rest.is_empty() { // List attributes. if ins.attributes.is_empty() { self.command_line.push_output(&format!( - " Insert {:x}: no attributes.", sh.value() + " Insert {:x}: no attributes.", + sh.value() )); } else { for attr in &ins.attributes { @@ -588,7 +690,8 @@ impl H7CAD { } } if !found_any { - self.command_line.push_error("ATTEDIT: no Insert entities in selection."); + self.command_line + .push_error("ATTEDIT: no Insert entities in selection."); } // If tag + value supplied, mutate attributes. if parts.len() == 2 && !parts[0].is_empty() { @@ -597,8 +700,11 @@ impl H7CAD { let mut changed = 0usize; self.push_undo_snapshot(i, "ATTEDIT"); for sh in &selected_handles { - if let Some(acadrust::EntityType::Insert(ins)) = - self.tabs[i].scene.document.entities_mut().find(|e| e.common().handle == *sh) + if let Some(acadrust::EntityType::Insert(ins)) = self.tabs[i] + .scene + .document + .entities_mut() + .find(|e| e.common().handle == *sh) { for attr in &mut ins.attributes { if attr.tag.to_uppercase() == tag_up { @@ -635,9 +741,16 @@ impl H7CAD { for entity in self.tabs[i].scene.document.entities_mut() { if let acadrust::EntityType::AttributeDefinition(ad) = entity { match sub.as_str() { - "ON" => { ad.flags.invisible = false; count += 1; } - "OFF" => { ad.flags.invisible = true; count += 1; } - "NORMAL" => { /* leave existing flags — they are already the "normal" state */ } + "ON" => { + ad.flags.invisible = false; + count += 1; + } + "OFF" => { + ad.flags.invisible = true; + count += 1; + } + "NORMAL" => { /* leave existing flags — they are already the "normal" state */ + } _ => {} } } @@ -648,19 +761,20 @@ impl H7CAD { )); } _ => { - self.command_line.push_info("Usage: ATTDISP ON | OFF | NORMAL"); + self.command_line + .push_info("Usage: ATTDISP ON | OFF | NORMAL"); } } } - "DONUT"|"DO" => { + "DONUT" | "DO" => { use crate::modules::home::draw::donut::DonutCommand; let cmd = DonutCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "CIRCLE"|"C" => { + "CIRCLE" | "C" => { use crate::modules::home::draw::circle::CircleCommand; let new_cmd = CircleCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -701,7 +815,7 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "ARC"|"A" => { + "ARC" | "A" => { use crate::modules::home::draw::arc::ArcCommand; let new_cmd = ArcCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -762,7 +876,7 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "RECT"|"RECTANG"|"REC" => { + "RECT" | "RECTANG" | "REC" => { use crate::modules::home::draw::shapes::RectCommand; let new_cmd = RectCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -780,7 +894,7 @@ impl H7CAD { self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "POLY"|"POLYGON"|"POL" => { + "POLY" | "POLYGON" | "POL" => { use crate::modules::home::draw::shapes::PolyCommand; let new_cmd = PolyCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -799,7 +913,7 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "PLINE"|"PL" => { + "PLINE" | "PL" => { use crate::modules::home::draw::polyline::PlineCommand; let new_cmd = PlineCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -807,9 +921,13 @@ impl H7CAD { } // ── Modify commands ──────────────────────────────────────────── - "MOVE"|"M" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "MOVE" | "M" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("MOVE"); @@ -824,9 +942,13 @@ impl H7CAD { } } - "COPY"|"CO" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "COPY" | "CO" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("COPY"); @@ -841,9 +963,13 @@ impl H7CAD { } } - "ROTATE"|"RO" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "ROTATE" | "RO" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("ROTATE"); @@ -858,7 +984,7 @@ impl H7CAD { } } - "POINT"|"PO" => { + "POINT" | "PO" => { use crate::modules::home::draw::point::PointCommand; let new_cmd = PointCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -872,14 +998,14 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "XLINE"|"XL"|"CONSTRUCTIONLINE" => { + "XLINE" | "XL" | "CONSTRUCTIONLINE" => { use crate::modules::home::draw::ray::XLineCommand; let new_cmd = XLineCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "HATCH"|"H" => { + "HATCH" | "H" => { use crate::modules::home::draw::hatch::HatchCommand; let outlines = self.tabs[i].scene.closed_outlines(); let new_cmd = HatchCommand::new(outlines); @@ -887,7 +1013,7 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "HATCHEDIT"|"HE" => { + "HATCHEDIT" | "HE" => { use crate::modules::home::draw::hatchedit::HatcheditCommand; // If a single hatch is already selected, skip the pick step. let sel = self.tabs[i].scene.selected_entities(); @@ -895,12 +1021,16 @@ impl H7CAD { let (h, _) = sel[0]; if let Some(model) = self.tabs[i].scene.hatches.get(&h).cloned() { let cmd = HatcheditCommand::with_handle( - h, model.name.clone(), model.scale, model.angle_offset, + h, + model.name.clone(), + model.scale, + model.angle_offset, ); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - self.command_line.push_error("HATCHEDIT: selected entity is not a hatch."); + self.command_line + .push_error("HATCHEDIT: selected entity is not a hatch."); } } else { let cmd = HatcheditCommand::new(); @@ -925,7 +1055,7 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "ELLIPSE"|"EL" => { + "ELLIPSE" | "EL" => { use crate::modules::home::draw::ellipse::EllipseCommand; let new_cmd = EllipseCommand::new(); self.command_line.push_info(&new_cmd.prompt()); @@ -946,16 +1076,20 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "SPLINE"|"SPL" => { + "SPLINE" | "SPL" => { use crate::modules::home::draw::spline::SplineCommand; let new_cmd = SplineCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "SCALE"|"SC" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "SCALE" | "SC" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("SCALE"); @@ -970,9 +1104,13 @@ impl H7CAD { } } - "MIRROR"|"MI" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "MIRROR" | "MI" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("MIRROR"); @@ -987,9 +1125,13 @@ impl H7CAD { } } - "ERASE"|"E" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "ERASE" | "E" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("ERASE"); @@ -1001,20 +1143,21 @@ impl H7CAD { self.tabs[i].scene.erase_entities(&handles); self.tabs[i].dirty = true; self.refresh_properties(); - self.command_line.push_output(&format!("{n} object(s) erased.")); + self.command_line + .push_output(&format!("{n} object(s) erased.")); } } // ── Annotate commands ────────────────────────────────────────── - "TEXT"|"T"|"DT" => { + "TEXT" | "T" | "DT" => { use crate::modules::annotate::text::TextCommand; let new_cmd = TextCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "DDEDIT"|"ED" => { - use crate::modules::annotate::ddedit::{DdeditCommand, entity_text}; + "DDEDIT" | "ED" => { + use crate::modules::annotate::ddedit::{entity_text, DdeditCommand}; // If a single text/mtext entity is already selected, skip the pick step. let sel = self.tabs[i].scene.selected_entities(); if sel.len() == 1 { @@ -1022,10 +1165,12 @@ impl H7CAD { if let Some(e) = self.tabs[i].scene.document.get_entity(h) { if let Some(cur) = entity_text(e) { let cmd = DdeditCommand::with_handle(h, cur.clone()); - self.command_line.push_info(&format!("DDEDIT Enter new text <{cur}>:")); + self.command_line + .push_info(&format!("DDEDIT Enter new text <{cur}>:")); self.tabs[i].active_cmd = Some(Box::new(cmd)); } else { - self.command_line.push_error("DDEDIT: selected entity is not text."); + self.command_line + .push_error("DDEDIT: selected entity is not text."); } } } else { @@ -1035,21 +1180,21 @@ impl H7CAD { } } - "MTEXT"|"MT" => { + "MTEXT" | "MT" => { use crate::modules::annotate::mtext::MTextCommand; let new_cmd = MTextCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "DIMALIGNED"|"DAL" => { + "DIMALIGNED" | "DAL" => { use crate::modules::annotate::aligned_dim::AlignedDimensionCommand; let cmd = AlignedDimensionCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMDIAMETER"|"DDI" => { + "DIMDIAMETER" | "DDI" => { use crate::modules::annotate::diameter_dim::DiameterDimensionCommand; let cmd = DiameterDimensionCommand::new(); self.command_line.push_info(&cmd.prompt()); @@ -1077,28 +1222,28 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "DIMORDINATE"|"DOR" => { + "DIMORDINATE" | "DOR" => { use crate::modules::annotate::ordinate_dim::OrdinateDimCommand; let new_cmd = OrdinateDimCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "LEADER"|"LE" => { + "LEADER" | "LE" => { use crate::modules::annotate::leader_cmd::LeaderCommand; let new_cmd = LeaderCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "MLEADER"|"MLD" => { + "MLEADER" | "MLD" => { use crate::modules::annotate::mleader_cmd::MLeaderCommand; let new_cmd = MLeaderCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "TOLERANCE"|"TOL" => { + "TOLERANCE" | "TOL" => { use crate::modules::annotate::tolerance_cmd::ToleranceCommand; let cmd = ToleranceCommand::new(); self.command_line.push_info(&cmd.prompt()); @@ -1112,9 +1257,10 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMCONTINUE"|"DCO" => { + "DIMCONTINUE" | "DCO" => { use crate::modules::annotate::dim_continue::DimContinueCommand; - let cmd = if let Some((p1, p2, dp, rot)) = find_last_linear_dim(&self.tabs[i].scene) { + let cmd = if let Some((p1, p2, dp, rot)) = find_last_linear_dim(&self.tabs[i].scene) + { DimContinueCommand::from_base(p1, p2, dp, rot) } else { DimContinueCommand::new() @@ -1123,9 +1269,10 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMBASELINE"|"DBA" => { + "DIMBASELINE" | "DBA" => { use crate::modules::annotate::dim_baseline::DimBaselineCommand; - let cmd = if let Some((p1, p2, dp, rot)) = find_last_linear_dim(&self.tabs[i].scene) { + let cmd = if let Some((p1, p2, dp, rot)) = find_last_linear_dim(&self.tabs[i].scene) + { DimBaselineCommand::from_base(p1, p2, dp, rot) } else { DimBaselineCommand::new() @@ -1141,120 +1288,126 @@ impl H7CAD { self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMEDIT"|"DED" => { + "DIMEDIT" | "DED" => { use crate::modules::annotate::dimedit::DimEditCommand; let cmd = DimEditCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMTEDIT"|"DIMTED" => { + "DIMTEDIT" | "DIMTED" => { use crate::modules::annotate::dimtedit::DimTeditCommand; let cmd = DimTeditCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMBREAK"|"DBR" => { + "DIMBREAK" | "DBR" => { use crate::modules::annotate::dimbreak::DimBreakCommand; let cmd = DimBreakCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMSPACE"|"DSPACE" => { + "DIMSPACE" | "DSPACE" => { use crate::modules::annotate::dimspace::DimSpaceCommand; let cmd = DimSpaceCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIMJOGLINE"|"DJL" => { + "DIMJOGLINE" | "DJL" => { use crate::modules::annotate::dimjogline::DimJogLineCommand; let cmd = DimJogLineCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "MLEADERADD"|"MLA" => { + "MLEADERADD" | "MLA" => { use crate::modules::annotate::mleader_edit::MLeaderAddCommand; let cmd = MLeaderAddCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "MLEADERREMOVE"|"MLR" => { + "MLEADERREMOVE" | "MLR" => { use crate::modules::annotate::mleader_edit::MLeaderRemoveCommand; let cmd = MLeaderRemoveCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "MLEADERALIGN"|"MLAL" => { + "MLEADERALIGN" | "MLAL" => { use crate::modules::annotate::mleader_edit::MLeaderAlignCommand; let cmd = MLeaderAlignCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "MLEADERCOLLECT"|"MLC" => { + "MLEADERCOLLECT" | "MLC" => { use crate::modules::annotate::mleader_edit::MLeaderCollectCommand; let cmd = MLeaderCollectCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "ZOOM EXTENTS"|"ZOOMEXTENTS"|"ZE" => { + "ZOOM EXTENTS" | "ZOOMEXTENTS" | "ZE" => { self.tabs[i].scene.fit_all(); self.command_line.push_output("Zoom Extents"); } - "ZOOM IN"|"ZI" => { + "ZOOM IN" | "ZI" => { self.tabs[i].scene.zoom_camera(1.0 / 1.5); self.command_line.push_output("Zoom In"); } - "ZOOM OUT"|"ZO" => { + "ZOOM OUT" | "ZO" => { self.tabs[i].scene.zoom_camera(1.5); self.command_line.push_output("Zoom Out"); } // ZOOM ALL — fit all entities (same as EXTENTS for now) - "ZOOM ALL"|"ZOOM A"|"ZA" => { + "ZOOM ALL" | "ZOOM A" | "ZA" => { self.tabs[i].scene.fit_all(); self.command_line.push_output("Zoom All"); } // ZOOM SCALE — set zoom factor (e.g. "ZOOM SCALE 2" or "ZS 0.5") cmd if cmd.starts_with("ZOOM SCALE ") || cmd.starts_with("ZS ") => { - let rest = cmd.split_once(' ') + let rest = cmd + .split_once(' ') .and_then(|(_, r)| r.split_once(' ').map(|(_, v)| v).or(Some(r))) .unwrap_or("1"); if let Ok(factor) = rest.trim().parse::() { if factor > 0.0 { self.tabs[i].scene.zoom_camera(1.0 / factor); - self.command_line.push_output(&format!("Zoom Scale ×{factor:.3}")); + self.command_line + .push_output(&format!("Zoom Scale ×{factor:.3}")); } } } - "PLOTWINDOW"|"PW" => { + "PLOTWINDOW" | "PW" => { use crate::modules::view::plot_window::PlotWindowCommand; let cmd = PlotWindowCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "ZOOM WINDOW"|"ZOOM W"|"ZW" => { + "ZOOM WINDOW" | "ZOOM W" | "ZW" => { use crate::modules::view::zoom_window::ZoomWindowCommand; let new_cmd = ZoomWindowCommand::new(); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "STRETCH"|"SS" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "STRETCH" | "SS" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("STRETCH"); @@ -1268,23 +1421,38 @@ impl H7CAD { } } - "FILLET"|"F" => { + "FILLET" | "F" => { use crate::modules::home::modify::fillet::FilletCommand; - let entities: Vec<_> = self.tabs[i].scene.entity_wires().iter() + let entities: Vec<_> = self.tabs[i] + .scene + .entity_wires() + .iter() .filter_map(|w| { let h = Scene::handle_from_wire_name(&w.name)?; - self.tabs[i].scene.document.get_entity(h).cloned().map(|e| (h, e)) - }).collect(); + self.tabs[i] + .scene + .document + .get_entity(h) + .cloned() + .map(|e| (h, e)) + }) + .collect(); let all_entities: Vec<_> = entities.into_iter().map(|(_, e)| e).collect(); let new_cmd = FilletCommand::new( - crate::modules::home::defaults::get_fillet_radius(), all_entities); + crate::modules::home::defaults::get_fillet_radius(), + all_entities, + ); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "ARRAY"|"AR"|"ARRAYRECT" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "ARRAY" | "AR" | "ARRAYRECT" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("ARRAYRECT"); @@ -1300,8 +1468,12 @@ impl H7CAD { } "ARRAYPOLAR" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("ARRAYPOLAR"); @@ -1317,8 +1489,12 @@ impl H7CAD { } "ARRAYPATH" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("ARRAYPATH"); @@ -1327,20 +1503,28 @@ impl H7CAD { } else { use crate::modules::home::modify::array::ArrayPathCommand; let wires = self.tabs[i].scene.wire_models_for(&handles); - let all_entities: Vec<_> = self.tabs[i].scene.entity_wires().iter() + let all_entities: Vec<_> = self.tabs[i] + .scene + .entity_wires() + .iter() .filter_map(|w| { let h = Scene::handle_from_wire_name(&w.name)?; self.tabs[i].scene.document.get_entity(h).cloned() - }).collect(); + }) + .collect(); let new_cmd = ArrayPathCommand::new(handles, wires, all_entities); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } } - "ARRAY3D"|"3DARRAY" => { - let handles: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().map(|(h, _)| h).collect(); + "ARRAY3D" | "3DARRAY" => { + let handles: Vec<_> = self.tabs[i] + .scene + .selected_entities() + .into_iter() + .map(|(h, _)| h) + .collect(); if handles.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("ARRAY3D"); @@ -1354,24 +1538,34 @@ impl H7CAD { } } - "CHAMFER"|"CHA" => { + "CHAMFER" | "CHA" => { use crate::modules::home::modify::fillet::ChamferCommand; - let entities: Vec<_> = self.tabs[i].scene.entity_wires().iter() + let entities: Vec<_> = self.tabs[i] + .scene + .entity_wires() + .iter() .filter_map(|w| { let h = Scene::handle_from_wire_name(&w.name)?; - self.tabs[i].scene.document.get_entity(h).cloned().map(|e| (h, e)) - }).collect(); + self.tabs[i] + .scene + .document + .get_entity(h) + .cloned() + .map(|e| (h, e)) + }) + .collect(); let all_entities: Vec<_> = entities.into_iter().map(|(_, e)| e).collect(); let new_cmd = ChamferCommand::new( - crate::modules::home::defaults::get_chamfer_dist1(), all_entities); + crate::modules::home::defaults::get_chamfer_dist1(), + all_entities, + ); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "EXPLODE"|"X" => { + "EXPLODE" | "X" => { use crate::modules::home::modify::explode::explode_entity; - let entities: Vec<_> = self.tabs[i].scene.selected_entities() - .into_iter().collect(); + let entities: Vec<_> = self.tabs[i].scene.selected_entities().into_iter().collect(); if entities.is_empty() { use crate::modules::home::select::SelectObjectsCommand; let cmd = SelectObjectsCommand::new("EXPLODE"); @@ -1382,7 +1576,11 @@ impl H7CAD { .iter() .filter_map(|(h, e)| { let pieces = explode_entity(e, &self.tabs[i].scene.document); - if pieces.is_empty() { None } else { Some((*h, pieces)) } + if pieces.is_empty() { + None + } else { + Some((*h, pieces)) + } }) .collect(); let exploded = replacements.len(); @@ -1398,60 +1596,89 @@ impl H7CAD { if exploded > 0 { self.tabs[i].dirty = true; self.refresh_properties(); - self.command_line.push_output(&format!("{exploded} object(s) exploded.")); + self.command_line + .push_output(&format!("{exploded} object(s) exploded.")); } else { - self.command_line.push_info("EXPLODE: no explodable objects selected."); + self.command_line + .push_info("EXPLODE: no explodable objects selected."); } } } - "OFFSET"|"O" => { + "OFFSET" | "O" => { use crate::modules::home::modify::offset::OffsetCommand; - let all_entities: Vec<_> = self.tabs[i].scene.entity_wires().iter() + let all_entities: Vec<_> = self.tabs[i] + .scene + .entity_wires() + .iter() .filter_map(|w| { let h = Scene::handle_from_wire_name(&w.name)?; self.tabs[i].scene.document.get_entity(h).cloned() - }).collect(); + }) + .collect(); let new_cmd = OffsetCommand::new( - crate::modules::home::defaults::get_offset_dist(), all_entities); + crate::modules::home::defaults::get_offset_dist(), + all_entities, + ); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "TRIM"|"TR" => { + "TRIM" | "TR" => { use crate::modules::home::modify::trim::TrimCommand; - let entities: Vec<_> = self.tabs[i].scene.entity_wires().iter() + let entities: Vec<_> = self.tabs[i] + .scene + .entity_wires() + .iter() .filter_map(|w| { let h = Scene::handle_from_wire_name(&w.name)?; - self.tabs[i].scene.document.get_entity(h).cloned().map(|e| (h, e)) - }).collect(); + self.tabs[i] + .scene + .document + .get_entity(h) + .cloned() + .map(|e| (h, e)) + }) + .collect(); let all_entities: Vec<_> = entities.into_iter().map(|(_, e)| e).collect(); let new_cmd = TrimCommand::new(all_entities); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "EXTEND"|"EX" => { + "EXTEND" | "EX" => { use crate::modules::home::modify::trim::ExtendCommand; - let entities: Vec<_> = self.tabs[i].scene.entity_wires().iter() + let entities: Vec<_> = self.tabs[i] + .scene + .entity_wires() + .iter() .filter_map(|w| { let h = Scene::handle_from_wire_name(&w.name)?; - self.tabs[i].scene.document.get_entity(h).cloned().map(|e| (h, e)) - }).collect(); + self.tabs[i] + .scene + .document + .get_entity(h) + .cloned() + .map(|e| (h, e)) + }) + .collect(); let all_entities: Vec<_> = entities.into_iter().map(|(_, e)| e).collect(); let new_cmd = ExtendCommand::new(all_entities); self.command_line.push_info(&new_cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(new_cmd)); } - "3DORBIT"|"3O" => { - self.command_line.push_info("3D Orbit: drag with right mouse button."); + "3DORBIT" | "3O" => { + self.command_line + .push_info("3D Orbit: drag with right mouse button."); } // ── Selection utilities ─────────────────────────────────────── - "SELECTALL"|"SA" => { + "SELECTALL" | "SA" => { use crate::scene::Scene; - let handles: Vec = self.tabs[i].scene.entity_wires() + let handles: Vec = self.tabs[i] + .scene + .entity_wires() .iter() .filter_map(|w| Scene::handle_from_wire_name(&w.name)) .collect(); @@ -1459,11 +1686,12 @@ impl H7CAD { for h in handles { self.tabs[i].scene.select_entity(h, false); } - self.command_line.push_output(&format!("SELECTALL: {} object(s) selected.", count)); + self.command_line + .push_output(&format!("SELECTALL: {} object(s) selected.", count)); self.refresh_properties(); } - "DESELECT"|"DE"|"DESELALL" => { + "DESELECT" | "DE" | "DESELALL" => { self.tabs[i].scene.deselect_all(); self.command_line.push_output("Deselected."); self.refresh_properties(); @@ -1473,26 +1701,37 @@ impl H7CAD { "LIST" | "LI" => { let selected: Vec<_> = self.tabs[i].scene.selected_entities(); if selected.is_empty() { - self.command_line.push_error("LIST: no entities selected. Select entities first."); + self.command_line + .push_error("LIST: no entities selected. Select entities first."); } else { for (handle, _) in &selected { if let Some(entity) = self.tabs[i].scene.document.get_entity(*handle) { let type_name = entity_type_name(entity); let common = entity.common(); - let color_str = common.color.index() + let color_str = common + .color + .index() .map(|c| c.to_string()) .unwrap_or_else(|| "ByLayer".to_string()); - let linetype = if common.linetype.is_empty() || common.linetype == "ByLayer" { - "ByLayer".to_string() - } else { - common.linetype.clone() - }; + let linetype = + if common.linetype.is_empty() || common.linetype == "ByLayer" { + "ByLayer".to_string() + } else { + common.linetype.clone() + }; // Entity-specific details let details = entity_list_details(entity); self.command_line.push_output(&format!( "{type_name} Handle:{:X} Layer:{} Color:{} LT:{}{}", - handle.value(), common.layer, color_str, linetype, - if details.is_empty() { String::new() } else { format!("\n {details}") } + handle.value(), + common.layer, + color_str, + linetype, + if details.is_empty() { + String::new() + } else { + format!("\n {details}") + } )); } } @@ -1500,42 +1739,42 @@ impl H7CAD { } // ── Break / Join ───────────────────────────────────────────────── - "JOIN"|"J" => { + "JOIN" | "J" => { use crate::modules::home::modify::join::JoinCommand; let cmd = JoinCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "BREAK"|"BR" => { + "BREAK" | "BR" => { use crate::modules::home::modify::break_cmd::BreakInteractiveCommand; let cmd = BreakInteractiveCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "BREAKATPOINT"|"BAP" => { + "BREAKATPOINT" | "BAP" => { use crate::modules::home::modify::break_cmd::BreakAtPointCommand; let cmd = BreakAtPointCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "PEDIT"|"PE" => { + "PEDIT" | "PE" => { use crate::modules::home::modify::pedit::PeditCommand; let cmd_obj = PeditCommand::new(); self.command_line.push_info(&cmd_obj.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd_obj)); } - "SPLINEDIT"|"SPE" => { + "SPLINEDIT" | "SPE" => { use crate::modules::home::modify::splinedit::SplineditCommand; let cmd_obj = SplineditCommand::new(); self.command_line.push_info(&cmd_obj.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd_obj)); } - "ATTEDIT"|"ATE"|"-ATTEDIT" => { + "ATTEDIT" | "ATE" | "-ATTEDIT" => { use crate::modules::home::modify::attedit::AtteditCommand; let cmd_obj = AtteditCommand::new(); self.command_line.push_info(&cmd_obj.prompt()); @@ -1547,17 +1786,20 @@ impl H7CAD { use crate::modules::home::modify::refedit::RefEditPickCommand; // If a session is already active, tell the user. if self.tabs[i].refedit_session.is_some() { - self.command_line.push_error( - "REFEDIT: a session is already active. Use REFCLOSE first." - ); + self.command_line + .push_error("REFEDIT: a session is already active. Use REFCLOSE first."); } else { // Check if a single INSERT is already selected. - let selected: Vec<_> = self.tabs[i].scene.selected_entities().into_iter().collect(); + let selected: Vec<_> = + self.tabs[i].scene.selected_entities().into_iter().collect(); if selected.len() == 1 { - if let Some(acadrust::EntityType::Insert(_)) = selected.first().map(|(_, e)| e) { + if let Some(acadrust::EntityType::Insert(_)) = + selected.first().map(|(_, e)| e) + { let handle = selected[0].0; // Skip pick phase — jump straight to begin. - let _ = self.dispatch_command(&format!("REFEDIT_BEGIN:{}", handle.value())); + let _ = + self.dispatch_command(&format!("REFEDIT_BEGIN:{}", handle.value())); return Task::none(); } } @@ -1568,18 +1810,20 @@ impl H7CAD { } cmd if cmd.starts_with("REFEDIT_BEGIN:") => { - use crate::modules::home::modify::refedit::{RefEditSession, apply_insert_transform}; + use crate::modules::home::modify::refedit::{ + apply_insert_transform, RefEditSession, + }; use acadrust::Handle; - let handle_u64: u64 = cmd["REFEDIT_BEGIN:".len()..] - .parse().unwrap_or(0); + let handle_u64: u64 = cmd["REFEDIT_BEGIN:".len()..].parse().unwrap_or(0); let insert_handle = Handle::new(handle_u64); // Get INSERT entity. let insert = match self.tabs[i].scene.document.get_entity(insert_handle) { Some(acadrust::EntityType::Insert(ins)) => ins.clone(), _ => { - self.command_line.push_error("REFEDIT: selected object is not an INSERT."); + self.command_line + .push_error("REFEDIT: selected object is not an INSERT."); return Task::none(); } }; @@ -1589,18 +1833,23 @@ impl H7CAD { let sy = insert.y_scale(); let sz = insert.z_scale(); if (sx - sy).abs() > 1e-6 || (sx - sz).abs() > 1e-6 { - self.command_line.push_error( - "REFEDIT: non-uniform scale inserts are not supported." - ); + self.command_line + .push_error("REFEDIT: non-uniform scale inserts are not supported."); return Task::none(); } // Find the block record. - let br_handle = match self.tabs[i].scene.document.block_records.get(&insert.block_name) { + let br_handle = match self.tabs[i] + .scene + .document + .block_records + .get(&insert.block_name) + { Some(br) => br.handle, None => { self.command_line.push_error(&format!( - "REFEDIT: block \"{}\" not found.", insert.block_name + "REFEDIT: block \"{}\" not found.", + insert.block_name )); return Task::none(); } @@ -1608,15 +1857,23 @@ impl H7CAD { // Collect block-local entities (skip structural Block/BlockEnd/AttDef). let block_entities: Vec<_> = { - let br = self.tabs[i].scene.document.block_records.get(&insert.block_name).unwrap(); + let br = self.tabs[i] + .scene + .document + .block_records + .get(&insert.block_name) + .unwrap(); br.entity_handles .iter() .filter_map(|h| self.tabs[i].scene.document.get_entity(*h).cloned()) - .filter(|e| !matches!(e, - acadrust::EntityType::Block(_) | - acadrust::EntityType::BlockEnd(_) | - acadrust::EntityType::AttributeDefinition(_) - )) + .filter(|e| { + !matches!( + e, + acadrust::EntityType::Block(_) + | acadrust::EntityType::BlockEnd(_) + | acadrust::EntityType::AttributeDefinition(_) + ) + }) .collect() }; @@ -1675,18 +1932,20 @@ impl H7CAD { self.command_line.push_info(&cmd_obj.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd_obj)); } else { - self.command_line.push_error("REFCLOSE: no REFEDIT session active."); + self.command_line + .push_error("REFCLOSE: no REFEDIT session active."); } } "REFCLOSE_SAVE" => { - use crate::modules::home::modify::refedit::apply_insert_inverse_transform; use crate::modules::home::modify::explode::normalize_entity_for_block; + use crate::modules::home::modify::refedit::apply_insert_inverse_transform; let session = match self.tabs[i].refedit_session.take() { Some(s) => s, None => { - self.command_line.push_error("REFCLOSE: no REFEDIT session active."); + self.command_line + .push_error("REFCLOSE: no REFEDIT session active."); return Task::none(); } }; @@ -1694,7 +1953,8 @@ impl H7CAD { self.push_undo_snapshot(i, "REFCLOSE"); // Collect the edited temp entities. - let new_entities: Vec = session.temp_handles + let new_entities: Vec = session + .temp_handles .iter() .filter_map(|h| self.tabs[i].scene.document.get_entity(*h).cloned()) .collect(); @@ -1715,8 +1975,11 @@ impl H7CAD { .collect(); // Remove old block entities from the document. - let old_handles: Vec<_> = match self.tabs[i].scene.document - .block_records.get(&session.block_name) + let old_handles: Vec<_> = match self.tabs[i] + .scene + .document + .block_records + .get(&session.block_name) { Some(br) => br.entity_handles.clone(), None => vec![], @@ -1725,8 +1988,11 @@ impl H7CAD { self.tabs[i].scene.document.remove_entity(*h); } // Flush the entity_handles list from the block record. - if let Some(br) = self.tabs[i].scene.document - .block_records.get_mut(&session.block_name) + if let Some(br) = self.tabs[i] + .scene + .document + .block_records + .get_mut(&session.block_name) { br.entity_handles.clear(); } @@ -1749,38 +2015,40 @@ impl H7CAD { let session = match self.tabs[i].refedit_session.take() { Some(s) => s, None => { - self.command_line.push_error("REFCLOSE: no REFEDIT session active."); + self.command_line + .push_error("REFCLOSE: no REFEDIT session active."); return Task::none(); } }; // Remove temp entities without modifying the block. self.tabs[i].scene.erase_entities(&session.temp_handles); self.tabs[i].scene.deselect_all(); - self.command_line.push_output("REFCLOSE: Changes discarded."); + self.command_line + .push_output("REFCLOSE: Changes discarded."); } - "ALIGN"|"AL" => { + "ALIGN" | "AL" => { use crate::modules::home::modify::align::AlignCommand; let cmd = AlignCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "LENGTHEN"|"LEN" => { + "LENGTHEN" | "LEN" => { use crate::modules::home::modify::lengthen::LengthenCommand; let cmd = LengthenCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "DIVIDE"|"DIV" => { + "DIVIDE" | "DIV" => { use crate::modules::home::inquiry::divide::DivideCommand; let cmd = DivideCommand::new(); self.command_line.push_info(&cmd.prompt()); self.tabs[i].active_cmd = Some(Box::new(cmd)); } - "MEASURE"|"ME" => { + "MEASURE" | "ME" => { use crate::modules::home::inquiry::divide::MeasureCommand; let cmd = MeasureCommand::new(); self.command_line.push_info(&cmd.prompt()); @@ -1788,7 +2056,7 @@ impl H7CAD { } // ── Inquiry ────────────────────────────────────────────────────── - "DIST"|"DI" => { + "DIST" | "DI" => { use crate::modules::home::inquiry::dist::DistCommand; let cmd = DistCommand::new(); self.command_line.push_info(&cmd.prompt()); @@ -1813,9 +2081,8 @@ impl H7CAD { "MASSPROP" => { let selected = self.tabs[i].scene.selected_entities(); if selected.is_empty() { - self.command_line.push_error( - "MASSPROP: no entities selected. Select entities first." - ); + self.command_line + .push_error("MASSPROP: no entities selected. Select entities first."); } else { for (handle, _) in &selected { if let Some(entity) = self.tabs[i].scene.document.get_entity(*handle) { @@ -1840,7 +2107,10 @@ impl H7CAD { let sel = self.tabs[i].scene.selected_entities(); if sel.is_empty() { // Flatten all entities - self.tabs[i].scene.document.entities() + self.tabs[i] + .scene + .document + .entities() .map(|e| e.common().handle) .collect() } else { @@ -1858,7 +2128,8 @@ impl H7CAD { } self.tabs[i].dirty = true; self.command_line.push_output(&format!( - "FLATTEN: {} entity(ies) moved to Z=0.", handles.len() + "FLATTEN: {} entity(ies) moved to Z=0.", + handles.len() )); self.refresh_properties(); } @@ -1873,16 +2144,20 @@ impl H7CAD { let rest = cmd.split_once(' ').map(|(_, r)| r.trim()).unwrap_or(""); let parts: Vec<&str> = rest.splitn(2, ' ').collect(); let prop = parts.first().map(|s| s.to_uppercase()).unwrap_or_default(); - let val = parts.get(1).map(|s| s.trim()).unwrap_or("").to_uppercase(); + let val = parts.get(1).map(|s| s.trim()).unwrap_or("").to_uppercase(); - let matched: Vec = self.tabs[i].scene.document + let matched: Vec = self.tabs[i] + .scene + .document .entities() .filter(|e| { let c = e.common(); match prop.as_str() { - "TYPE" => entity_type_name(e).to_uppercase() == val, - "LAYER" => c.layer.to_uppercase() == val, - "COLOR" => c.color.index() + "TYPE" => entity_type_name(e).to_uppercase() == val, + "LAYER" => c.layer.to_uppercase() == val, + "COLOR" => c + .color + .index() .map(|n| n.to_string() == val) .unwrap_or(val == "BYLAYER"), "LINETYPE" => c.linetype.to_uppercase() == val, @@ -1893,19 +2168,18 @@ impl H7CAD { .collect(); if prop.is_empty() { - self.command_line.push_info( - "Usage: QSELECT TYPE|LAYER|COLOR|LINETYPE " - ); + self.command_line + .push_info("Usage: QSELECT TYPE|LAYER|COLOR|LINETYPE "); } else if matched.is_empty() { - self.command_line.push_output("QSELECT: no matching entities."); + self.command_line + .push_output("QSELECT: no matching entities."); } else { self.tabs[i].scene.deselect_all(); for h in &matched { self.tabs[i].scene.select_entity(*h, false); } - self.command_line.push_output(&format!( - "QSELECT: {} entity(ies) selected.", matched.len() - )); + self.command_line + .push_output(&format!("QSELECT: {} entity(ies) selected.", matched.len())); self.refresh_properties(); } } @@ -1919,10 +2193,12 @@ impl H7CAD { let type_name = entity_type_name(e); let key = match &filter { Some(f) if f == "LAYER" => layer.clone(), - Some(f) if f == "TYPE" => type_name.to_string(), + Some(f) if f == "TYPE" => type_name.to_string(), Some(f) => { // Filter by layer name - if layer.to_uppercase() != *f { continue; } + if layer.to_uppercase() != *f { + continue; + } type_name.to_string() } None => type_name.to_string(), @@ -1933,7 +2209,8 @@ impl H7CAD { for (k, n) in &counts { self.command_line.push_output(&format!(" {k}: {n}")); } - self.command_line.push_output(&format!("COUNT: {total} entity(ies) total.")); + self.command_line + .push_output(&format!("COUNT: {total} entity(ies) total.")); } "DATAEXTRACTION" | "EATTEXT" | "ATTEXT" => { @@ -1945,12 +2222,17 @@ impl H7CAD { // FIND — list all Text/MText/Dimension containing // FIND REPLACE — replace first occurrence (case-insensitive) // FINDALL REPLACE — replace all occurrences - cmd if cmd == "FIND" || cmd.starts_with("FIND ") || cmd == "FINDALL" || cmd.starts_with("FINDALL ") => { + cmd if cmd == "FIND" + || cmd.starts_with("FIND ") + || cmd == "FINDALL" + || cmd.starts_with("FINDALL ") => + { let all_mode = cmd.starts_with("FINDALL"); let rest = cmd.split_once(' ').map(|(_, r)| r.trim()).unwrap_or(""); // Split at " REPLACE " keyword (case-insensitive) - let (search, replacement) = if let Some(pos) = rest.to_uppercase().find(" REPLACE ") { + let (search, replacement) = if let Some(pos) = rest.to_uppercase().find(" REPLACE ") + { (&rest[..pos], Some(rest[pos + 9..].trim())) } else { (rest, None) @@ -1961,7 +2243,9 @@ impl H7CAD { } else { let search_lc = search.to_lowercase(); let mut count = 0usize; - let handles: Vec = self.tabs[i].scene.document + let handles: Vec = self.tabs[i] + .scene + .document .entities() .filter_map(|e| { let txt = entity_text_content(e)?; @@ -1981,7 +2265,8 @@ impl H7CAD { handles.iter().copied().take(1).collect() }; if targets.is_empty() { - self.command_line.push_output(&format!("FIND: \"{}\" not found.", search)); + self.command_line + .push_output(&format!("FIND: \"{}\" not found.", search)); } else { self.push_undo_snapshot(i, "FIND/REPLACE"); for h in &targets { @@ -2000,25 +2285,30 @@ impl H7CAD { } else { // List mode if handles.is_empty() { - self.command_line.push_output(&format!("FIND: \"{}\" not found.", search)); + self.command_line + .push_output(&format!("FIND: \"{}\" not found.", search)); } else { for h in &handles { if let Some(e) = self.tabs[i].scene.document.get_entity(*h) { let txt = entity_text_content(e).unwrap_or_default(); self.command_line.push_output(&format!( - " Handle {:X}: \"{}\"", h.value(), txt + " Handle {:X}: \"{}\"", + h.value(), + txt )); } } self.command_line.push_output(&format!( - "FIND: {} match(es) for \"{}\".", handles.len(), search + "FIND: {} match(es) for \"{}\".", + handles.len(), + search )); } } } } - "HELP"|"?" => { + "HELP" | "?" => { self.command_line.push_output( "Draw: LINE CIRCLE ARC PLINE RECTANG(RECT) POLYGON(POLY) POINT ELLIPSE SPLINE RAY XLINE HATCH DONUT REVCLOUD WIPEOUT MLINE ATTDEF | \ Modify: MOVE COPY ROTATE SCALE MIRROR ERASE OFFSET EXTEND FILLET CHAMFER STRETCH EXPLODE TRIM BREAK JOIN LENGTHEN ALIGN PEDIT | \ @@ -2074,7 +2364,8 @@ impl H7CAD { self.command_line.push_error("Usage: SHORTCUTS SET e.g. SHORTCUTS SET CTRL+D DIST"); } else { self.shortcut_overrides.insert(key.clone(), cmd_str.clone()); - self.command_line.push_output(&format!("Shortcut set: {key} → {cmd_str}")); + self.command_line + .push_output(&format!("Shortcut set: {key} → {cmd_str}")); } } "CLEAR" | "DELETE" | "REMOVE" => { @@ -2082,13 +2373,16 @@ impl H7CAD { if key.is_empty() { self.command_line.push_error("Usage: SHORTCUTS CLEAR "); } else if self.shortcut_overrides.remove(&key).is_some() { - self.command_line.push_output(&format!("Shortcut '{key}' removed.")); + self.command_line + .push_output(&format!("Shortcut '{key}' removed.")); } else { - self.command_line.push_error(&format!("Shortcut '{key}' not found.")); + self.command_line + .push_error(&format!("Shortcut '{key}' not found.")); } } _ => { - self.command_line.push_info("Usage: SHORTCUTS LIST | SET | CLEAR "); + self.command_line + .push_info("Usage: SHORTCUTS LIST | SET | CLEAR "); } } } @@ -2096,27 +2390,31 @@ impl H7CAD { // ── Color Scheme / Theme selector ───────────────────────────── cmd if cmd == "COLORSCHEME" || cmd.starts_with("COLORSCHEME ") => { use iced::Theme; - let sub = cmd.split_once(' ').map(|(_, r)| r.trim()).unwrap_or("").to_uppercase(); + let sub = cmd + .split_once(' ') + .map(|(_, r)| r.trim()) + .unwrap_or("") + .to_uppercase(); // Map name to Theme variant. let theme: Option = match sub.as_str() { - "DARK" => Some(Theme::Dark), - "LIGHT" => Some(Theme::Light), - "DRACULA" => Some(Theme::Dracula), - "NORD" => Some(Theme::Nord), - "SOLARIZED_LIGHT" | "SOLARIZEDLIGHT" => Some(Theme::SolarizedLight), - "SOLARIZED_DARK" | "SOLARIZEDDARK" => Some(Theme::SolarizedDark), - "GRUVBOX_LIGHT" | "GRUVBOXLIGHT" => Some(Theme::GruvboxLight), - "GRUVBOX_DARK" | "GRUVBOXDARK" => Some(Theme::GruvboxDark), - "TOKYONIGHT" | "TOKYO_NIGHT" => Some(Theme::TokyoNight), + "DARK" => Some(Theme::Dark), + "LIGHT" => Some(Theme::Light), + "DRACULA" => Some(Theme::Dracula), + "NORD" => Some(Theme::Nord), + "SOLARIZED_LIGHT" | "SOLARIZEDLIGHT" => Some(Theme::SolarizedLight), + "SOLARIZED_DARK" | "SOLARIZEDDARK" => Some(Theme::SolarizedDark), + "GRUVBOX_LIGHT" | "GRUVBOXLIGHT" => Some(Theme::GruvboxLight), + "GRUVBOX_DARK" | "GRUVBOXDARK" => Some(Theme::GruvboxDark), + "TOKYONIGHT" | "TOKYO_NIGHT" => Some(Theme::TokyoNight), "TOKYONIGHTSTORM" | "TOKYO_NIGHT_STORM" => Some(Theme::TokyoNightStorm), "TOKYONIGHTLIGHT" | "TOKYO_NIGHT_LIGHT" => Some(Theme::TokyoNightLight), - "KANAGAWAWAVE" | "KANAGAWA_WAVE" => Some(Theme::KanagawaWave), - "KANAGAWADRAGON" | "KANAGAWA_DRAGON" => Some(Theme::KanagawaDragon), - "KANAGAWALOTUS" | "KANAGAWA_LOTUS" => Some(Theme::KanagawaLotus), - "MOONFLY" => Some(Theme::Moonfly), - "NIGHTFLY" => Some(Theme::Nightfly), - "OXOCARBON" => Some(Theme::Oxocarbon), - "FERRA" => Some(Theme::Ferra), + "KANAGAWAWAVE" | "KANAGAWA_WAVE" => Some(Theme::KanagawaWave), + "KANAGAWADRAGON" | "KANAGAWA_DRAGON" => Some(Theme::KanagawaDragon), + "KANAGAWALOTUS" | "KANAGAWA_LOTUS" => Some(Theme::KanagawaLotus), + "MOONFLY" => Some(Theme::Moonfly), + "NIGHTFLY" => Some(Theme::Nightfly), + "OXOCARBON" => Some(Theme::Oxocarbon), + "FERRA" => Some(Theme::Ferra), "" | "LIST" | "?" => { self.command_line.push_output( "Available themes: DARK LIGHT DRACULA NORD SOLARIZED_LIGHT SOLARIZED_DARK \ @@ -2126,27 +2424,32 @@ impl H7CAD { return Task::none(); } _ => { - self.command_line.push_error(&format!("COLORSCHEME: unknown theme '{}'. Type COLORSCHEME LIST for options.", sub)); + self.command_line.push_error(&format!( + "COLORSCHEME: unknown theme '{}'. Type COLORSCHEME LIST for options.", + sub + )); return Task::none(); } }; if let Some(t) = theme { let name = format!("{:?}", t); - self.command_line.push_output(&format!("Color scheme set to '{name}'.")); + self.command_line + .push_output(&format!("Color scheme set to '{name}'.")); return Task::done(Message::SetTheme(t)); } return Task::none(); } // ── Layout Manager GUI ───────────────────────────────────────── - "LAYOUTMANAGER"|"LAYOUTPANEL" => { + "LAYOUTMANAGER" | "LAYOUTPANEL" => { return Task::done(Message::LayoutManagerOpen); } // ── Layout / viewport ────────────────────────────────────────── - "MVIEW"|"MV" => { + "MVIEW" | "MV" => { if self.tabs[i].scene.current_layout == "Model" { - self.command_line.push_error("MVIEW: switch to a paper space layout first."); + self.command_line + .push_error("MVIEW: switch to a paper space layout first."); } else { use crate::modules::layout::mview::MviewCommand; let new_cmd = MviewCommand::new(); @@ -2156,7 +2459,7 @@ impl H7CAD { } // ── MSPACE / PSPACE ─────────────────────────────────────────── - "MS"|"MSPACE" => { + "MS" | "MSPACE" => { return Task::done(Message::MspaceCommand); } "PSPACE" => { @@ -2168,28 +2471,47 @@ impl H7CAD { let sub = cmd.split_whitespace().nth(1).unwrap_or("").to_uppercase(); let scene = &self.tabs[i].scene; if scene.current_layout == "Model" { - self.command_line.push_error("VPORTS: switch to a paper space layout first."); + self.command_line + .push_error("VPORTS: switch to a paper space layout first."); } else if sub.is_empty() { // ── List existing viewports ────────────────────────── let layout_block = scene.current_layout_block_handle_pub(); - let viewports: Vec<_> = scene.document.entities() + let viewports: Vec<_> = scene + .document + .entities() .filter_map(|e| { if let acadrust::EntityType::Viewport(vp) = e { if vp.id > 1 && vp.common.owner_handle == layout_block { - Some((vp.id, vp.center.clone(), vp.width, vp.height, vp.custom_scale, vp.status.is_on, vp.status.locked)) - } else { None } - } else { None } + Some(( + vp.id, + vp.center.clone(), + vp.width, + vp.height, + vp.custom_scale, + vp.status.is_on, + vp.status.locked, + )) + } else { + None + } + } else { + None + } }) .collect(); if viewports.is_empty() { self.command_line.push_info("No viewports. Use MVIEW to create one, or VPORTS 2H / 2V / 4 / SINGLE."); } else { - self.command_line.push_output(&format!("{} viewport(s) in layout \"{}\":", viewports.len(), scene.current_layout)); + self.command_line.push_output(&format!( + "{} viewport(s) in layout \"{}\":", + viewports.len(), + scene.current_layout + )); for (id, center, w, h, scale, is_on, locked) in &viewports { let state = match (is_on, locked) { - (true, true) => "On, Locked", + (true, true) => "On, Locked", (true, false) => "On", - (false, _) => "Off", + (false, _) => "Off", }; self.command_line.push_output(&format!( " VP #{id}: {w:.1}×{h:.1} @ ({:.1},{:.1}) scale={scale:.4} [{state}]", @@ -2219,13 +2541,13 @@ impl H7CAD { let margin = 5.0_f64; // mm margin around the usable area let uw = paper_w - 2.0 * margin; // usable width let uh = paper_h - 2.0 * margin; // usable height - // Collect rectangle specs: (cx, cz, w, h) in mm + // Collect rectangle specs: (cx, cz, w, h) in mm let rects: Vec<(f64, f64, f64, f64)> = match sub.as_str() { "2H" => { // Two viewports side by side (horizontal split) let vw = (uw - 2.0) / 2.0; vec![ - (margin + vw / 2.0, margin + uh / 2.0, vw, uh), + (margin + vw / 2.0, margin + uh / 2.0, vw, uh), (margin + vw + 2.0 + vw / 2.0, margin + uh / 2.0, vw, uh), ] } @@ -2234,7 +2556,7 @@ impl H7CAD { let vh = (uh - 2.0) / 2.0; vec![ (margin + uw / 2.0, margin + vh + 2.0 + vh / 2.0, uw, vh), - (margin + uw / 2.0, margin + vh / 2.0, uw, vh), + (margin + uw / 2.0, margin + vh / 2.0, uw, vh), ] } "4" => { @@ -2242,10 +2564,15 @@ impl H7CAD { let vw = (uw - 2.0) / 2.0; let vh = (uh - 2.0) / 2.0; vec![ - (margin + vw / 2.0, margin + vh + 2.0 + vh / 2.0, vw, vh), - (margin + vw + 2.0 + vw / 2.0, margin + vh + 2.0 + vh / 2.0, vw, vh), - (margin + vw / 2.0, margin + vh / 2.0, vw, vh), - (margin + vw + 2.0 + vw / 2.0, margin + vh / 2.0, vw, vh), + (margin + vw / 2.0, margin + vh + 2.0 + vh / 2.0, vw, vh), + ( + margin + vw + 2.0 + vw / 2.0, + margin + vh + 2.0 + vh / 2.0, + vw, + vh, + ), + (margin + vw / 2.0, margin + vh / 2.0, vw, vh), + (margin + vw + 2.0 + vw / 2.0, margin + vh / 2.0, vw, vh), ] } "SINGLE" | "1" => { @@ -2254,7 +2581,7 @@ impl H7CAD { } _ => { self.command_line.push_error( - "VPORTS: unknown option. Use VPORTS 2H | 2V | 4 | SINGLE" + "VPORTS: unknown option. Use VPORTS 2H | 2V | 4 | SINGLE", ); vec![] } @@ -2262,13 +2589,20 @@ impl H7CAD { if !rects.is_empty() { // Remove existing user viewports in this layout first. let layout_block = self.tabs[i].scene.current_layout_block_handle_pub(); - let to_erase: Vec = self.tabs[i].scene.document.entities() + let to_erase: Vec = self.tabs[i] + .scene + .document + .entities() .filter_map(|e| { if let acadrust::EntityType::Viewport(vp) = e { if vp.id > 1 && vp.common.owner_handle == layout_block { Some(vp.common.handle) - } else { None } - } else { None } + } else { + None + } + } else { + None + } }) .collect(); self.push_undo_snapshot(i, "VPORTS"); @@ -2277,9 +2611,9 @@ impl H7CAD { for (cx, cz, w, h) in &rects { let mut vp = acadrust::entities::Viewport::new(); vp.center = acadrust::types::Vector3::new(*cx, 0.0, *cz); - vp.width = *w; + vp.width = *w; vp.height = *h; - vp.id = 2; // commit_entity will assign unique IDs + vp.id = 2; // commit_entity will assign unique IDs match self.tabs[i].scene.document.add_entity_to_layout( acadrust::EntityType::Viewport(vp), &layout_name, @@ -2295,13 +2629,20 @@ impl H7CAD { // Re-assign unique IDs (1 + existing max per viewport). let layout_block2 = self.tabs[i].scene.current_layout_block_handle_pub(); let mut id_counter = 2_i16; - let handles: Vec = self.tabs[i].scene.document.entities() + let handles: Vec = self.tabs[i] + .scene + .document + .entities() .filter_map(|e| { if let acadrust::EntityType::Viewport(vp) = e { if vp.id >= 2 && vp.common.owner_handle == layout_block2 { Some(vp.common.handle) - } else { None } - } else { None } + } else { + None + } + } else { + None + } }) .collect(); for h in handles { @@ -2314,7 +2655,9 @@ impl H7CAD { } self.tabs[i].dirty = true; self.command_line.push_output(&format!( - "VPORTS: created {} viewport(s) [{}].", rects.len(), sub + "VPORTS: created {} viewport(s) [{}].", + rects.len(), + sub )); } } @@ -2324,9 +2667,11 @@ impl H7CAD { "VPLAYER" => { let scene = &self.tabs[i].scene; if scene.current_layout == "Model" { - self.command_line.push_error("VPLAYER: switch to a paper space layout first."); + self.command_line + .push_error("VPLAYER: switch to a paper space layout first."); } else if scene.active_viewport.is_none() { - self.command_line.push_error("VPLAYER: enter a viewport first (double-click or MS)."); + self.command_line + .push_error("VPLAYER: enter a viewport first (double-click or MS)."); } else { use crate::modules::layout::vplayer::VplayerCommand; let vp_handle = scene.active_viewport.unwrap(); @@ -2335,13 +2680,24 @@ impl H7CAD { if let Some(acadrust::EntityType::Viewport(vp)) = scene.document.get_entity(vp_handle) { - vp.frozen_layers.iter().filter_map(|h| { - scene.document.layers.iter().find(|l| l.handle == *h).map(|l| l.name.clone()) - }).collect() - } else { vec![] } + vp.frozen_layers + .iter() + .filter_map(|h| { + scene + .document + .layers + .iter() + .find(|l| l.handle == *h) + .map(|l| l.name.clone()) + }) + .collect() + } else { + vec![] + } }; if frozen_names.is_empty() { - self.command_line.push_info("VPLAYER: no frozen layers in active viewport."); + self.command_line + .push_info("VPLAYER: no frozen layers in active viewport."); } else { self.command_line.push_info(&format!( "VPLAYER: frozen layers: {}", @@ -2360,13 +2716,15 @@ impl H7CAD { let parts: Vec<&str> = cmd.split_whitespace().collect(); let option = parts.get(1).unwrap_or(&"").to_uppercase(); let i = self.active_tab; - let selected: Vec = self.tabs[i].scene + let selected: Vec = self.tabs[i] + .scene .selected_entities() .iter() .map(|(h, _)| *h) .collect(); if selected.is_empty() { - self.command_line.push_error("DRAWORDER: select entities first."); + self.command_line + .push_error("DRAWORDER: select entities first."); } else { // Parse relative target handle for ABOVE/UNDER. let relative_target: Option<(bool, acadrust::Handle)> = match option.as_str() { @@ -2382,7 +2740,7 @@ impl H7CAD { }; let to_front_opt = match option.as_str() { "F" | "FRONT" => Some(true), - "B" | "BACK" => Some(false), + "B" | "BACK" => Some(false), _ => None, }; @@ -2390,29 +2748,39 @@ impl H7CAD { self.push_undo_snapshot(i, "DRAWORDER"); let block_handle = self.tabs[i].scene.current_layout_block_handle_pub(); let doc = &mut self.tabs[i].scene.document; - let table_handle = doc.objects.iter() - .find_map(|(h, obj)| { - if let ObjectType::SortEntitiesTable(t) = obj { - if t.block_owner_handle == block_handle { Some(*h) } else { None } - } else { None } - }); - let get_or_create = |doc: &mut acadrust::CadDocument, block_handle| -> acadrust::Handle { - if let Some(th) = doc.objects.iter() - .find_map(|(h, obj)| { - if let ObjectType::SortEntitiesTable(t) = obj { - if t.block_owner_handle == block_handle { Some(*h) } else { None } - } else { None } - }) - { - th + let table_handle = doc.objects.iter().find_map(|(h, obj)| { + if let ObjectType::SortEntitiesTable(t) = obj { + if t.block_owner_handle == block_handle { + Some(*h) + } else { + None + } } else { - let nh = acadrust::Handle::new(doc.next_handle()); - let mut table = SortEntitiesTable::for_block(block_handle); - table.handle = nh; - doc.objects.insert(nh, ObjectType::SortEntitiesTable(table)); - nh + None } - }; + }); + let get_or_create = + |doc: &mut acadrust::CadDocument, block_handle| -> acadrust::Handle { + if let Some(th) = doc.objects.iter().find_map(|(h, obj)| { + if let ObjectType::SortEntitiesTable(t) = obj { + if t.block_owner_handle == block_handle { + Some(*h) + } else { + None + } + } else { + None + } + }) { + th + } else { + let nh = acadrust::Handle::new(doc.next_handle()); + let mut table = SortEntitiesTable::for_block(block_handle); + table.handle = nh; + doc.objects.insert(nh, ObjectType::SortEntitiesTable(table)); + nh + } + }; let th = table_handle.unwrap_or_else(|| { let nh = acadrust::Handle::new(doc.next_handle()); let mut table = SortEntitiesTable::for_block(block_handle); @@ -2421,24 +2789,36 @@ impl H7CAD { nh }); let _ = get_or_create; // suppress unused warning - if let Some(ObjectType::SortEntitiesTable(table)) = doc.objects.get_mut(&th) { + if let Some(ObjectType::SortEntitiesTable(table)) = doc.objects.get_mut(&th) + { if let Some((above, target)) = relative_target { for h in &selected { - if above { table.move_above(*h, target); } - else { table.move_below(*h, target); } + if above { + table.move_above(*h, target); + } else { + table.move_below(*h, target); + } } let rel = if above { "above" } else { "below" }; self.command_line.push_info(&format!( - "DRAWORDER: moved {} entities {} {:x}.", selected.len(), rel, target.value() + "DRAWORDER: moved {} entities {} {:x}.", + selected.len(), + rel, + target.value() )); } else if let Some(to_front) = to_front_opt { for h in &selected { - if to_front { table.bring_to_front(*h); } - else { table.send_to_back(*h); } + if to_front { + table.bring_to_front(*h); + } else { + table.send_to_back(*h); + } } let dir = if to_front { "front" } else { "back" }; self.command_line.push_info(&format!( - "DRAWORDER: moved {} entities to {}.", selected.len(), dir + "DRAWORDER: moved {} entities to {}.", + selected.len(), + dir )); } } @@ -2465,33 +2845,48 @@ impl H7CAD { let sub = parts.get(0).map(|s| s.to_uppercase()).unwrap_or_default(); match sub.as_str() { "" | "LIST" | "?" => { - let info: Vec = self.tabs[i].scene.document.layers.iter().map(|l| { - let state = if l.flags.frozen { "frozen" } - else if l.flags.off { "off" } - else if l.flags.locked { "locked" } - else { "on" }; - format!("{}({})", l.name, state) - }).collect(); - self.command_line.push_output(&format!("Layers: {}", info.join(", "))); + let info: Vec = self.tabs[i] + .scene + .document + .layers + .iter() + .map(|l| { + let state = if l.flags.frozen { + "frozen" + } else if l.flags.off { + "off" + } else if l.flags.locked { + "locked" + } else { + "on" + }; + format!("{}({})", l.name, state) + }) + .collect(); + self.command_line + .push_output(&format!("Layers: {}", info.join(", "))); } "NEW" | "N" => { let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); if name.is_empty() { self.command_line.push_error("Usage: LAYER NEW "); } else if self.tabs[i].scene.document.layers.contains(&name) { - self.command_line.push_error(&format!("LAYER: '{}' already exists.", name)); + self.command_line + .push_error(&format!("LAYER: '{}' already exists.", name)); } else { let layer = Layer::new(&name); let _ = self.tabs[i].scene.document.layers.add(layer); self.push_undo_snapshot(i, "LAYER NEW"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("LAYER: '{}' created.", name)); + self.command_line + .push_output(&format!("LAYER: '{}' created.", name)); } } "ON" => { for name in &parts[1..] { if let Some(l) = self.tabs[i].scene.document.layers.get_mut(name) { - l.flags.off = false; l.flags.frozen = false; + l.flags.off = false; + l.flags.frozen = false; } } self.push_undo_snapshot(i, "LAYER ON"); @@ -2553,25 +2948,33 @@ impl H7CAD { let layer_name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); let color_str = parts.get(2).map(|s| s.trim()).unwrap_or(""); if let Ok(idx) = color_str.parse::() { - if let Some(l) = self.tabs[i].scene.document.layers.get_mut(&layer_name) { + if let Some(l) = self.tabs[i].scene.document.layers.get_mut(&layer_name) + { l.color = acadrust::types::Color::from_index(idx); self.push_undo_snapshot(i, "LAYER COLOR"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("LAYER: '{}' color set to ACI {}.", layer_name, idx)); + self.command_line.push_output(&format!( + "LAYER: '{}' color set to ACI {}.", + layer_name, idx + )); } else { - self.command_line.push_error(&format!("LAYER: '{}' not found.", layer_name)); + self.command_line + .push_error(&format!("LAYER: '{}' not found.", layer_name)); } } else { - self.command_line.push_error("Usage: LAYER COLOR "); + self.command_line + .push_error("Usage: LAYER COLOR "); } } "SET" | "S" | "CURRENT" => { let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); if self.tabs[i].scene.document.layers.contains(&name) { self.tabs[i].layers.current_layer = name.clone(); - self.command_line.push_output(&format!("LAYER: current layer set to '{}'.", name)); + self.command_line + .push_output(&format!("LAYER: current layer set to '{}'.", name)); } else { - self.command_line.push_error(&format!("LAYER: '{}' not found.", name)); + self.command_line + .push_error(&format!("LAYER: '{}' not found.", name)); } } _ => { @@ -2584,25 +2987,35 @@ impl H7CAD { // ── UCS management ─────────────────────────────────────────── cmd if cmd == "UCS" || cmd.starts_with("UCS ") => { + use super::helpers::{ucs_rotated_z, ucs_to_wcs, ucs_z_axis}; use acadrust::tables::Ucs; use acadrust::types::Vector3; - use super::helpers::{ucs_to_wcs, ucs_z_axis, ucs_rotated_z}; let parts: Vec<&str> = cmd.splitn(4, ' ').collect(); let sub = parts.get(1).map(|s| s.to_uppercase()).unwrap_or_default(); match sub.as_str() { "" | "LIST" | "?" => { - let active_name = self.tabs[i].active_ucs.as_ref() + let active_name = self.tabs[i] + .active_ucs + .as_ref() .map(|u| u.name.clone()) .unwrap_or_else(|| "WCS".into()); - let names: Vec = self.tabs[i].scene.document - .ucss.iter().map(|u| u.name.clone()).collect(); + let names: Vec = self.tabs[i] + .scene + .document + .ucss + .iter() + .map(|u| u.name.clone()) + .collect(); if names.is_empty() { self.command_line.push_output(&format!( - "Active UCS: {} | No named UCSs defined.", active_name + "Active UCS: {} | No named UCSs defined.", + active_name )); } else { self.command_line.push_output(&format!( - "Active UCS: {} | Named: {}", active_name, names.join(", ") + "Active UCS: {} | Named: {}", + active_name, + names.join(", ") )); } } @@ -2622,7 +3035,8 @@ impl H7CAD { }; self.tabs[i].scene.document.ucss.add_or_replace(ucs); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("UCS '{}' saved.", name)); + self.command_line + .push_output(&format!("UCS '{}' saved.", name)); } } "DELETE" | "DEL" | "D" => { @@ -2631,14 +3045,17 @@ impl H7CAD { self.command_line.push_error("Usage: UCS DELETE "); } else if self.tabs[i].scene.document.ucss.remove(&name).is_some() { self.tabs[i].dirty = true; - self.command_line.push_output(&format!("UCS '{}' deleted.", name)); + self.command_line + .push_output(&format!("UCS '{}' deleted.", name)); } else { - self.command_line.push_error(&format!("UCS '{}' not found.", name)); + self.command_line + .push_error(&format!("UCS '{}' not found.", name)); } } "W" | "WORLD" => { self.tabs[i].active_ucs = None; - self.command_line.push_output("UCS reset to World Coordinate System."); + self.command_line + .push_output("UCS reset to World Coordinate System."); } // UCS ORIGIN x,y,z — shift the active UCS origin, keep axes "ORIGIN" | "O" => { @@ -2650,9 +3067,13 @@ impl H7CAD { } else { pt }; - let ucs = self.tabs[i].active_ucs.get_or_insert_with(|| Ucs::new("*ACTIVE*")); + let ucs = self.tabs[i] + .active_ucs + .get_or_insert_with(|| Ucs::new("*ACTIVE*")); ucs.origin = Vector3::new( - wcs_origin.x as f64, wcs_origin.y as f64, wcs_origin.z as f64, + wcs_origin.x as f64, + wcs_origin.y as f64, + wcs_origin.z as f64, ); self.command_line.push_output(&format!( "UCS origin set to ({:.4}, {:.4}, {:.4}).", @@ -2668,35 +3089,40 @@ impl H7CAD { if let Some(angle_deg) = deg { let rad = angle_deg.to_radians(); let current = self.tabs[i].active_ucs.as_ref(); - let origin = current.map(|u| { - glam::Vec3::new( - u.origin.x as f32, u.origin.y as f32, u.origin.z as f32, - ) - }).unwrap_or(glam::Vec3::ZERO); + let origin = current + .map(|u| { + glam::Vec3::new( + u.origin.x as f32, + u.origin.y as f32, + u.origin.z as f32, + ) + }) + .unwrap_or(glam::Vec3::ZERO); let mut new_ucs = ucs_rotated_z(origin, rad); // If already had axes, compose rotation on top if let Some(ref ucs) = self.tabs[i].active_ucs { let old_x = glam::Vec3::new( - ucs.x_axis.x as f32, ucs.x_axis.y as f32, ucs.x_axis.z as f32, + ucs.x_axis.x as f32, + ucs.x_axis.y as f32, + ucs.x_axis.z as f32, ); let old_y = glam::Vec3::new( - ucs.y_axis.x as f32, ucs.y_axis.y as f32, ucs.y_axis.z as f32, + ucs.y_axis.x as f32, + ucs.y_axis.y as f32, + ucs.y_axis.z as f32, ); let z_ax = ucs_z_axis(ucs); let rot = glam::Quat::from_axis_angle(z_ax, rad); let nx = rot * old_x; let ny = rot * old_y; - new_ucs.x_axis = Vector3::new( - nx.x as f64, nx.y as f64, nx.z as f64, - ); - new_ucs.y_axis = Vector3::new( - ny.x as f64, ny.y as f64, ny.z as f64, - ); + new_ucs.x_axis = + Vector3::new(nx.x as f64, nx.y as f64, nx.z as f64); + new_ucs.y_axis = + Vector3::new(ny.x as f64, ny.y as f64, ny.z as f64); } self.tabs[i].active_ucs = Some(new_ucs); - self.command_line.push_output(&format!( - "UCS rotated {:.2}° around Z.", angle_deg - )); + self.command_line + .push_output(&format!("UCS rotated {:.2}° around Z.", angle_deg)); } else { self.command_line.push_error("Usage: UCS Z "); } @@ -2706,19 +3132,24 @@ impl H7CAD { let deg: Option = parts.get(2).and_then(|s| s.trim().parse().ok()); if let Some(angle_deg) = deg { let rad = angle_deg.to_radians(); - let ucs = self.tabs[i].active_ucs.get_or_insert_with(|| Ucs::new("*ACTIVE*")); + let ucs = self.tabs[i] + .active_ucs + .get_or_insert_with(|| Ucs::new("*ACTIVE*")); let x_ax = glam::Vec3::new( - ucs.x_axis.x as f32, ucs.x_axis.y as f32, ucs.x_axis.z as f32, + ucs.x_axis.x as f32, + ucs.x_axis.y as f32, + ucs.x_axis.z as f32, ); let old_y = glam::Vec3::new( - ucs.y_axis.x as f32, ucs.y_axis.y as f32, ucs.y_axis.z as f32, + ucs.y_axis.x as f32, + ucs.y_axis.y as f32, + ucs.y_axis.z as f32, ); let rot = glam::Quat::from_axis_angle(x_ax, rad); let ny = rot * old_y; ucs.y_axis = Vector3::new(ny.x as f64, ny.y as f64, ny.z as f64); - self.command_line.push_output(&format!( - "UCS rotated {:.2}° around X.", angle_deg - )); + self.command_line + .push_output(&format!("UCS rotated {:.2}° around X.", angle_deg)); } else { self.command_line.push_error("Usage: UCS X "); } @@ -2728,19 +3159,24 @@ impl H7CAD { let deg: Option = parts.get(2).and_then(|s| s.trim().parse().ok()); if let Some(angle_deg) = deg { let rad = angle_deg.to_radians(); - let ucs = self.tabs[i].active_ucs.get_or_insert_with(|| Ucs::new("*ACTIVE*")); + let ucs = self.tabs[i] + .active_ucs + .get_or_insert_with(|| Ucs::new("*ACTIVE*")); let y_ax = glam::Vec3::new( - ucs.y_axis.x as f32, ucs.y_axis.y as f32, ucs.y_axis.z as f32, + ucs.y_axis.x as f32, + ucs.y_axis.y as f32, + ucs.y_axis.z as f32, ); let old_x = glam::Vec3::new( - ucs.x_axis.x as f32, ucs.x_axis.y as f32, ucs.x_axis.z as f32, + ucs.x_axis.x as f32, + ucs.x_axis.y as f32, + ucs.x_axis.z as f32, ); let rot = glam::Quat::from_axis_angle(y_ax, rad); let nx = rot * old_x; ucs.x_axis = Vector3::new(nx.x as f64, nx.y as f64, nx.z as f64); - self.command_line.push_output(&format!( - "UCS rotated {:.2}° around Y.", angle_deg - )); + self.command_line + .push_output(&format!("UCS rotated {:.2}° around Y.", angle_deg)); } else { self.command_line.push_error("Usage: UCS Y "); } @@ -2750,7 +3186,8 @@ impl H7CAD { let name = sub.clone(); if let Some(named) = self.tabs[i].scene.document.ucss.get(&name).cloned() { self.tabs[i].active_ucs = Some(named); - self.command_line.push_output(&format!("UCS '{}' activated.", name)); + self.command_line + .push_output(&format!("UCS '{}' activated.", name)); } else { self.command_line.push_error(&format!( "UCS '{}' not found. Usage: UCS LIST | SAVE | DELETE | W | ORIGIN x,y,z | X/Y/Z ", @@ -2767,14 +3204,18 @@ impl H7CAD { let sub = parts.get(1).map(|s| s.to_uppercase()).unwrap_or_default(); match sub.as_str() { "" | "LIST" | "?" => { - let views: Vec = self.tabs[i].scene.document - .views.iter().map(|v| v.name.clone()).collect(); + let views: Vec = self.tabs[i] + .scene + .document + .views + .iter() + .map(|v| v.name.clone()) + .collect(); if views.is_empty() { self.command_line.push_output("No named views saved."); } else { - self.command_line.push_output(&format!( - "Named views: {}", views.join(", ") - )); + self.command_line + .push_output(&format!("Named views: {}", views.join(", "))); } } "SAVE" | "S" => { @@ -2784,7 +3225,8 @@ impl H7CAD { } else { let new_view = self.tabs[i].scene.current_as_named_view(&name); self.tabs[i].scene.document.views.add_or_replace(new_view); - self.command_line.push_output(&format!("View '{}' saved.", name)); + self.command_line + .push_output(&format!("View '{}' saved.", name)); } } "DELETE" | "DEL" | "D" => { @@ -2793,9 +3235,11 @@ impl H7CAD { self.command_line.push_error("Usage: VIEW DELETE "); } else { if self.tabs[i].scene.document.views.remove(&name).is_some() { - self.command_line.push_output(&format!("View '{}' deleted.", name)); + self.command_line + .push_output(&format!("View '{}' deleted.", name)); } else { - self.command_line.push_error(&format!("View '{}' not found.", name)); + self.command_line + .push_error(&format!("View '{}' not found.", name)); } } } @@ -2807,9 +3251,11 @@ impl H7CAD { let found = self.tabs[i].scene.document.views.get(&name).cloned(); if let Some(v) = found { self.tabs[i].scene.restore_named_view(&v); - self.command_line.push_output(&format!("View '{}' restored.", v.name)); + self.command_line + .push_output(&format!("View '{}' restored.", v.name)); } else { - self.command_line.push_error(&format!("View '{}' not found.", name)); + self.command_line + .push_error(&format!("View '{}' not found.", name)); } } } @@ -2819,7 +3265,8 @@ impl H7CAD { let found = self.tabs[i].scene.document.views.get(&name).cloned(); if let Some(v) = found { self.tabs[i].scene.restore_named_view(&v); - self.command_line.push_output(&format!("View '{}' restored.", v.name)); + self.command_line + .push_output(&format!("View '{}' restored.", v.name)); } else { self.command_line.push_error( "Usage: VIEW LIST | VIEW SAVE | VIEW RESTORE | VIEW DELETE " @@ -2832,7 +3279,7 @@ impl H7CAD { // ── DimStyle management ─────────────────────────────────────── // TABLESTYLE — Table Style Manager. cmd if cmd == "TABLESTYLE" || cmd == "TS" || cmd.starts_with("TABLESTYLE ") => { - use acadrust::objects::{TableStyle, ObjectType}; + use acadrust::objects::{ObjectType, TableStyle}; let raw_rest = cmd.split_once(' ').map(|(_, r)| r.trim()).unwrap_or(""); let parts: Vec<&str> = raw_rest.split_whitespace().collect(); let sub = parts.first().map(|s| s.to_uppercase()).unwrap_or_default(); @@ -2842,14 +3289,28 @@ impl H7CAD { } "LIST" | "?" => { let doc = &self.tabs[i].scene.document; - let styles: Vec = doc.objects.values() - .filter_map(|o| if let ObjectType::TableStyle(s) = o { Some(s) } else { None }) - .map(|s| format!("{} (h_margin:{:.2} v_margin:{:.2})", s.name, s.horizontal_margin, s.vertical_margin)) + let styles: Vec = doc + .objects + .values() + .filter_map(|o| { + if let ObjectType::TableStyle(s) = o { + Some(s) + } else { + None + } + }) + .map(|s| { + format!( + "{} (h_margin:{:.2} v_margin:{:.2})", + s.name, s.horizontal_margin, s.vertical_margin + ) + }) .collect(); if styles.is_empty() { self.command_line.push_output("No table styles."); } else { - self.command_line.push_output(&format!("TableStyles:\n {}", styles.join("\n "))); + self.command_line + .push_output(&format!("TableStyles:\n {}", styles.join("\n "))); } } "NEW" | "N" => { @@ -2862,23 +3323,30 @@ impl H7CAD { matches!(o, ObjectType::TableStyle(s) if s.name.eq_ignore_ascii_case(&name)) }); if exists { - self.command_line.push_error(&format!("TABLESTYLE: '{}' already exists.", name)); + self.command_line + .push_error(&format!("TABLESTYLE: '{}' already exists.", name)); } else { self.push_undo_snapshot(i, "TABLESTYLE NEW"); let mut style = TableStyle::standard(); style.name = name.clone(); - let nh = acadrust::Handle::new(self.tabs[i].scene.document.next_handle()); + let nh = acadrust::Handle::new( + self.tabs[i].scene.document.next_handle(), + ); style.handle = nh; - self.tabs[i].scene.document.objects.insert(nh, ObjectType::TableStyle(style)); + self.tabs[i] + .scene + .document + .objects + .insert(nh, ObjectType::TableStyle(style)); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("TABLESTYLE: '{}' created.", name)); + self.command_line + .push_output(&format!("TABLESTYLE: '{}' created.", name)); } } } _ => { - self.command_line.push_error( - "Usage: TABLESTYLE [LIST|NEW ]" - ); + self.command_line + .push_error("Usage: TABLESTYLE [LIST|NEW ]"); } } } @@ -2902,20 +3370,26 @@ impl H7CAD { "LIST" | "?" => { let doc = &self.tabs[i].scene.document; let current = &doc.header.multiline_style; - let styles: Vec = doc.objects.values() - .filter_map(|o| if let ObjectType::MLineStyle(s) = o { Some(s) } else { None }) + let styles: Vec = doc + .objects + .values() + .filter_map(|o| { + if let ObjectType::MLineStyle(s) = o { + Some(s) + } else { + None + } + }) .map(|s| { let cur = if &s.name == current { " (current)" } else { "" }; - format!("{} [{}]{}", - s.name, - s.elements.len(), - cur) + format!("{} [{}]{}", s.name, s.elements.len(), cur) }) .collect(); if styles.is_empty() { self.command_line.push_output("No multiline styles."); } else { - self.command_line.push_output(&format!("MLineStyles:\n {}", styles.join("\n "))); + self.command_line + .push_output(&format!("MLineStyles:\n {}", styles.join("\n "))); } } "NEW" | "N" => { @@ -2928,18 +3402,24 @@ impl H7CAD { matches!(o, ObjectType::MLineStyle(s) if s.name.eq_ignore_ascii_case(&name)) }); if exists { - self.command_line.push_error(&format!("MLSTYLE: '{}' already exists.", name)); + self.command_line + .push_error(&format!("MLSTYLE: '{}' already exists.", name)); } else { self.push_undo_snapshot(i, "MLSTYLE NEW"); let mut style = MLineStyle::standard(); style.name = name.clone(); - let nh = acadrust::Handle::new(self.tabs[i].scene.document.next_handle()); - style.handle = nh; - self.tabs[i].scene.document.objects.insert( - nh, ObjectType::MLineStyle(style) + let nh = acadrust::Handle::new( + self.tabs[i].scene.document.next_handle(), ); + style.handle = nh; + self.tabs[i] + .scene + .document + .objects + .insert(nh, ObjectType::MLineStyle(style)); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("MLSTYLE: '{}' created.", name)); + self.command_line + .push_output(&format!("MLSTYLE: '{}' created.", name)); } } } @@ -2956,43 +3436,58 @@ impl H7CAD { self.push_undo_snapshot(i, "MLSTYLE SET"); self.tabs[i].scene.document.header.multiline_style = name.clone(); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("MLSTYLE: current style set to '{}'.", name)); + self.command_line.push_output(&format!( + "MLSTYLE: current style set to '{}'.", + name + )); } else { - self.command_line.push_error(&format!("MLSTYLE: '{}' not found.", name)); + self.command_line + .push_error(&format!("MLSTYLE: '{}' not found.", name)); } } } "DEL" | "DELETE" => { let name = parts.get(1).copied().unwrap_or("").to_string(); if name.is_empty() || name.eq_ignore_ascii_case("Standard") { - self.command_line.push_error("Cannot delete the Standard style."); + self.command_line + .push_error("Cannot delete the Standard style."); } else { let doc = &self.tabs[i].scene.document; - let handle = doc.objects.iter() - .find_map(|(&h, o)| { - if let ObjectType::MLineStyle(s) = o { - if s.name.eq_ignore_ascii_case(&name) { Some(h) } else { None } - } else { None } - }); + let handle = doc.objects.iter().find_map(|(&h, o)| { + if let ObjectType::MLineStyle(s) = o { + if s.name.eq_ignore_ascii_case(&name) { + Some(h) + } else { + None + } + } else { + None + } + }); if let Some(h) = handle { self.push_undo_snapshot(i, "MLSTYLE DEL"); self.tabs[i].scene.document.objects.remove(&h); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("MLSTYLE: '{}' deleted.", name)); + self.command_line + .push_output(&format!("MLSTYLE: '{}' deleted.", name)); } else { - self.command_line.push_error(&format!("MLSTYLE: '{}' not found.", name)); + self.command_line + .push_error(&format!("MLSTYLE: '{}' not found.", name)); } } } _ => { - self.command_line.push_error( - "Usage: MLSTYLE [LIST|NEW |SET |DEL ]" - ); + self.command_line + .push_error("Usage: MLSTYLE [LIST|NEW |SET |DEL ]"); } } } - cmd if cmd == "DIMSTYLE" || cmd == "DDIM" || cmd.starts_with("DIMSTYLE ") || cmd.starts_with("DDIM ") => { + cmd if cmd == "DIMSTYLE" + || cmd == "DDIM" + || cmd.starts_with("DIMSTYLE ") + || cmd.starts_with("DDIM ") => + { use acadrust::tables::DimStyle; let raw_rest = cmd.split_once(' ').map(|(_, r)| r.trim()).unwrap_or(""); let parts: Vec<&str> = raw_rest.split_whitespace().collect(); @@ -3003,14 +3498,18 @@ impl H7CAD { return Task::done(Message::DimStyleDialogOpen); } "LIST" | "?" => { - let styles: Vec = self.tabs[i].scene.document - .dim_styles.iter() + let styles: Vec = self.tabs[i] + .scene + .document + .dim_styles + .iter() .map(|s| format!("{}(txt:{:.2} asz:{:.2})", s.name, s.dimtxt, s.dimasz)) .collect(); if styles.is_empty() { self.command_line.push_output("No dim styles defined."); } else { - self.command_line.push_output(&format!("DimStyles: {}", styles.join(", "))); + self.command_line + .push_output(&format!("DimStyles: {}", styles.join(", "))); } } "NEW" | "N" => { @@ -3018,13 +3517,15 @@ impl H7CAD { if name.is_empty() { self.command_line.push_error("Usage: DIMSTYLE NEW "); } else if self.tabs[i].scene.document.dim_styles.contains(&name) { - self.command_line.push_error(&format!("DIMSTYLE: '{}' already exists.", name)); + self.command_line + .push_error(&format!("DIMSTYLE: '{}' already exists.", name)); } else { let style = DimStyle::new(&name); let _ = self.tabs[i].scene.document.dim_styles.add(style); self.push_undo_snapshot(i, "DIMSTYLE NEW"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("DIMSTYLE: '{}' created.", name)); + self.command_line + .push_output(&format!("DIMSTYLE: '{}' created.", name)); } } "SET" | "S" => { @@ -3034,21 +3535,49 @@ impl H7CAD { let prop = parts.get(2).map(|s| s.to_lowercase()).unwrap_or_default(); let val_str = parts.get(3).map(|s| s.trim()).unwrap_or(""); if let Ok(val) = val_str.parse::() { - if let Some(ds) = self.tabs[i].scene.document.dim_styles.get_mut(&style_name) { + if let Some(ds) = + self.tabs[i].scene.document.dim_styles.get_mut(&style_name) + { match prop.as_str() { - "dimtxt" => { ds.dimtxt = val; } - "dimasz" => { ds.dimasz = val; } - "dimdli" => { ds.dimdli = val; } - "dimexo" => { ds.dimexo = val; } - "dimexe" => { ds.dimexe = val; } - "dimgap" => { ds.dimgap = val; } - "dimscale" => { ds.dimscale = val; } - "dimlfac" => { ds.dimlfac = val; } - "dimdle" => { ds.dimdle = val; } - "dimtvp" => { ds.dimtvp = val; } - "dimcen" => { ds.dimcen = val; } - "dimtsz" => { ds.dimtsz = val; } - "dimfxl" => { ds.dimfxl = val; } + "dimtxt" => { + ds.dimtxt = val; + } + "dimasz" => { + ds.dimasz = val; + } + "dimdli" => { + ds.dimdli = val; + } + "dimexo" => { + ds.dimexo = val; + } + "dimexe" => { + ds.dimexe = val; + } + "dimgap" => { + ds.dimgap = val; + } + "dimscale" => { + ds.dimscale = val; + } + "dimlfac" => { + ds.dimlfac = val; + } + "dimdle" => { + ds.dimdle = val; + } + "dimtvp" => { + ds.dimtvp = val; + } + "dimcen" => { + ds.dimcen = val; + } + "dimtsz" => { + ds.dimtsz = val; + } + "dimfxl" => { + ds.dimfxl = val; + } _ => { self.command_line.push_error(&format!( "DIMSTYLE: unknown property '{}'. Try: dimtxt dimasz dimdli dimexo dimexe dimgap dimscale dimlfac dimdle dimcen dimtsz", prop @@ -3058,17 +3587,21 @@ impl H7CAD { } self.push_undo_snapshot(i, "DIMSTYLE SET"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("DIMSTYLE: '{style_name}'.{prop} = {val:.3}")); + self.command_line.push_output(&format!( + "DIMSTYLE: '{style_name}'.{prop} = {val:.3}" + )); } else { - self.command_line.push_error(&format!("DIMSTYLE: '{}' not found.", style_name)); + self.command_line + .push_error(&format!("DIMSTYLE: '{}' not found.", style_name)); } } else { - self.command_line.push_error("Usage: DIMSTYLE SET "); + self.command_line + .push_error("Usage: DIMSTYLE SET "); } } _ => { self.command_line.push_info( - "Usage: DIMSTYLE LIST | NEW | SET " + "Usage: DIMSTYLE LIST | NEW | SET ", ); } } @@ -3076,40 +3609,66 @@ impl H7CAD { // ── MLeader Style management ────────────────────────────────── cmd if cmd == "MLEADERSTYLE" || cmd.starts_with("MLEADERSTYLE ") => { - use acadrust::objects::{ObjectType, MultiLeaderStyle}; + use acadrust::objects::{MultiLeaderStyle, ObjectType}; let raw_rest = cmd.trim_start_matches("MLEADERSTYLE").trim(); let parts: Vec<&str> = raw_rest.split_whitespace().collect(); let sub = parts.first().map(|s| s.to_uppercase()).unwrap_or_default(); match sub.as_str() { "" | "LIST" | "?" => { - let styles: Vec = self.tabs[i].scene.document - .objects.values() - .filter_map(|o| if let ObjectType::MultiLeaderStyle(s) = o { Some(format!("{}(txt:{:.2} asz:{:.2})", s.name, s.text_height, s.arrowhead_size)) } else { None }) + let styles: Vec = self.tabs[i] + .scene + .document + .objects + .values() + .filter_map(|o| { + if let ObjectType::MultiLeaderStyle(s) = o { + Some(format!( + "{}(txt:{:.2} asz:{:.2})", + s.name, s.text_height, s.arrowhead_size + )) + } else { + None + } + }) .collect(); let current = &self.tabs[i].active_mleader_style; if styles.is_empty() { - self.command_line.push_output(&format!("MLeader styles: (none) active: {current}")); + self.command_line + .push_output(&format!("MLeader styles: (none) active: {current}")); } else { - self.command_line.push_output(&format!("MLeader styles: {} active: {current}", styles.join(", "))); + self.command_line.push_output(&format!( + "MLeader styles: {} active: {current}", + styles.join(", ") + )); } } "NEW" | "N" => { let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); if name.is_empty() { - self.command_line.push_error("Usage: MLEADERSTYLE NEW "); + self.command_line + .push_error("Usage: MLEADERSTYLE NEW "); } else { - let already_exists = self.tabs[i].scene.document.objects.values() - .any(|o| matches!(o, ObjectType::MultiLeaderStyle(s) if s.name == name)); + let already_exists = self.tabs[i].scene.document.objects.values().any( + |o| matches!(o, ObjectType::MultiLeaderStyle(s) if s.name == name), + ); if already_exists { - self.command_line.push_error(&format!("MLEADERSTYLE: '{}' already exists.", name)); + self.command_line.push_error(&format!( + "MLEADERSTYLE: '{}' already exists.", + name + )); } else { let handle = self.tabs[i].scene.document.allocate_handle(); let mut style = MultiLeaderStyle::new(&name); style.handle = handle; - self.tabs[i].scene.document.objects.insert(handle, ObjectType::MultiLeaderStyle(style)); + self.tabs[i] + .scene + .document + .objects + .insert(handle, ObjectType::MultiLeaderStyle(style)); self.push_undo_snapshot(i, "MLEADERSTYLE NEW"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("MLEADERSTYLE: '{}' created.", name)); + self.command_line + .push_output(&format!("MLEADERSTYLE: '{}' created.", name)); } } } @@ -3120,14 +3679,36 @@ impl H7CAD { let prop = parts.get(2).map(|s| s.to_lowercase()).unwrap_or_default(); let val_str = parts.get(3).map(|s| s.trim()).unwrap_or(""); if let Ok(val) = val_str.parse::() { - let style_entry = self.tabs[i].scene.document.objects.values_mut() - .find_map(|o| if let ObjectType::MultiLeaderStyle(s) = o { if s.name == style_name { Some(s) } else { None } } else { None }); + let style_entry = self.tabs[i] + .scene + .document + .objects + .values_mut() + .find_map(|o| { + if let ObjectType::MultiLeaderStyle(s) = o { + if s.name == style_name { + Some(s) + } else { + None + } + } else { + None + } + }); if let Some(s) = style_entry { match prop.as_str() { - "text_height" | "textheight" | "txth" => { s.text_height = val; } - "arrowhead_size" | "arrowsize" | "asz" => { s.arrowhead_size = val; } - "landing_distance" | "landing" | "dogleg" => { s.landing_distance = val; } - "landing_gap" | "gap" => { s.landing_gap = val; } + "text_height" | "textheight" | "txth" => { + s.text_height = val; + } + "arrowhead_size" | "arrowsize" | "asz" => { + s.arrowhead_size = val; + } + "landing_distance" | "landing" | "dogleg" => { + s.landing_distance = val; + } + "landing_gap" | "gap" => { + s.landing_gap = val; + } _ => { self.command_line.push_error(&format!( "MLEADERSTYLE: unknown property '{}'. Try: text_height arrowhead_size landing_distance landing_gap", prop @@ -3137,26 +3718,38 @@ impl H7CAD { } self.push_undo_snapshot(i, "MLEADERSTYLE SET"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("MLEADERSTYLE: '{style_name}'.{prop} = {val:.3}")); + self.command_line.push_output(&format!( + "MLEADERSTYLE: '{style_name}'.{prop} = {val:.3}" + )); } else { - self.command_line.push_error(&format!("MLEADERSTYLE: '{}' not found.", style_name)); + self.command_line.push_error(&format!( + "MLEADERSTYLE: '{}' not found.", + style_name + )); } } else { - self.command_line.push_error("Usage: MLEADERSTYLE SET "); + self.command_line + .push_error("Usage: MLEADERSTYLE SET "); } } "CURRENT" | "C" | "ACTIVE" => { let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); if name.is_empty() { - self.command_line.push_output(&format!("Current MLeader style: {}", self.tabs[i].active_mleader_style)); + self.command_line.push_output(&format!( + "Current MLeader style: {}", + self.tabs[i].active_mleader_style + )); } else { let exists = name == "Standard" || self.tabs[i].scene.document.objects.values() .any(|o| matches!(o, ObjectType::MultiLeaderStyle(s) if s.name == name)); if exists { self.tabs[i].active_mleader_style = name.clone(); - self.command_line.push_output(&format!("MLEADERSTYLE: current style set to '{name}'.")); + self.command_line.push_output(&format!( + "MLEADERSTYLE: current style set to '{name}'." + )); } else { - self.command_line.push_error(&format!("MLEADERSTYLE: '{}' not found.", name)); + self.command_line + .push_error(&format!("MLEADERSTYLE: '{}' not found.", name)); } } } @@ -3169,7 +3762,11 @@ impl H7CAD { } // ── TextStyle / Style management ────────────────────────────── - cmd if cmd == "STYLE" || cmd == "TEXTSTYLE" || cmd.starts_with("STYLE ") || cmd.starts_with("TEXTSTYLE ") => { + cmd if cmd == "STYLE" + || cmd == "TEXTSTYLE" + || cmd.starts_with("STYLE ") + || cmd.starts_with("TEXTSTYLE ") => + { let (prefix, rest) = if cmd.starts_with("TEXTSTYLE") { ("TEXTSTYLE", cmd.trim_start_matches("TEXTSTYLE").trim()) } else { @@ -3182,38 +3779,54 @@ impl H7CAD { return Task::done(Message::TextStyleDialogOpen); } "" | "LIST" | "?" => { - let styles: Vec = self.tabs[i].scene.document - .text_styles.iter() - .map(|s| format!("{} (font: {}, w: {:.2}, oblique: {:.1}°)", - s.name, s.font_file, s.width_factor, s.oblique_angle.to_degrees())) + let styles: Vec = self.tabs[i] + .scene + .document + .text_styles + .iter() + .map(|s| { + format!( + "{} (font: {}, w: {:.2}, oblique: {:.1}°)", + s.name, + s.font_file, + s.width_factor, + s.oblique_angle.to_degrees() + ) + }) .collect(); if styles.is_empty() { self.command_line.push_output("No text styles defined."); } else { - self.command_line.push_output(&format!("Text styles: {}", styles.join(" | "))); + self.command_line + .push_output(&format!("Text styles: {}", styles.join(" | "))); } } "SET" | "S" => { // STYLE SET — set active text style (for future text commands) let name = parts.get(1).map(|s| s.trim()).unwrap_or(""); if self.tabs[i].scene.document.text_styles.get(name).is_some() { - self.command_line.push_output(&format!("{prefix}: active style set to '{name}'.")); + self.command_line + .push_output(&format!("{prefix}: active style set to '{name}'.")); } else { - self.command_line.push_error(&format!("{prefix}: style '{name}' not found.")); + self.command_line + .push_error(&format!("{prefix}: style '{name}' not found.")); } } "NEW" | "N" => { let name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); if name.is_empty() { - self.command_line.push_error(&format!("Usage: {prefix} NEW ")); + self.command_line + .push_error(&format!("Usage: {prefix} NEW ")); } else if self.tabs[i].scene.document.text_styles.contains(&name) { - self.command_line.push_error(&format!("{prefix}: style '{name}' already exists.")); + self.command_line + .push_error(&format!("{prefix}: style '{name}' already exists.")); } else { let style = acadrust::tables::TextStyle::new(&name); let _ = self.tabs[i].scene.document.text_styles.add(style); self.push_undo_snapshot(i, "STYLE NEW"); self.tabs[i].dirty = true; - self.command_line.push_output(&format!("{prefix}: style '{name}' created.")); + self.command_line + .push_output(&format!("{prefix}: style '{name}' created.")); } } "FONT" | "F" => { @@ -3221,14 +3834,20 @@ impl H7CAD { let style_name = parts.get(1).map(|s| s.trim()).unwrap_or("").to_string(); let font = parts.get(2).map(|s| s.trim()).unwrap_or("").to_string(); if style_name.is_empty() || font.is_empty() { - self.command_line.push_error(&format!("Usage: {prefix} FONT