Merge pull request #384 from KevinGriffin-new/fix/matchprop-text

Match text style and height between TEXT/MTEXT objects (#361).

MATCHPROP copied only the generic properties, so Text->Text and
Text->MText matching left the destination's style and height unchanged.
The MatchProperties handler now also carries style + height between
text-like objects, both directions, like AutoCAD's "Text" special
property. bump_geometry re-tessellates so matched text repaints at its
new size.

Conflict: the fix (command_driver.rs) auto-merged; only the additive
test block in automation.rs conflicted with tests main added since the
PR branched. Resolved by keeping all four tests.

# Conflicts:
#	src/app/automation.rs
This commit is contained in:
Hakan Seven committed 2026-07-16 11:33:46 +03:00
commit 5afee1d71f
2 files changed
+89

No files matched your search

+63
View File
@@ -651,6 +651,69 @@ mod tests {
}
}
#[test]
fn matchprop_matches_text_style_and_height() {
// MATCHPROP between text objects must carry the text-specific
// properties (style, height) to TEXT and MTEXT destinations, not just
// the generic layer/color/linetype set. Regression for #361.
use crate::command::StepInput;
use acadrust::{EntityType, MText, Text};
let mut app = OpenCADStudio::new_for_test();
app.automation_op(r#"{"op":"new"}"#);
let i = app.active_tab;
let mut src = Text::new();
src.value = "SRC".into();
src.height = 5.0;
src.style = "BIG".into();
let src_h = app.tabs[i].scene.add_entity(EntityType::Text(src));
let mut dst_text = Text::new();
dst_text.value = "DST".into();
dst_text.height = 1.0;
let dst_text_h = app.tabs[i].scene.add_entity(EntityType::Text(dst_text));
let mut dst_mtext = MText::new();
dst_mtext.value = "DSTM".into();
dst_mtext.height = 2.0;
let dst_mtext_h = app.tabs[i].scene.add_entity(EntityType::MText(dst_mtext));
// Drive the interactive command exactly as the viewport does:
// phase 1 source pick, phase 2 destination selection.
let _ = app.run_command_line("MATCHPROP");
assert!(app.tabs[i].active_cmd.is_some(), "MATCHPROP must start");
let _ = app.feed_command(StepInput::EntityPick(src_h, glam::DVec3::ZERO));
let _ = app.feed_command(StepInput::SelectionComplete(vec![
dst_text_h,
dst_mtext_h,
]));
let doc = &app.tabs[i].scene.document;
match doc.get_entity(dst_text_h) {
Some(EntityType::Text(t)) => {
assert_eq!(t.style, "BIG", "TEXT destination must take source style");
assert!(
(t.height - 5.0).abs() < 1e-9,
"TEXT destination must take source height, got {}",
t.height
);
}
other => panic!("dest TEXT missing: {other:?}"),
}
match doc.get_entity(dst_mtext_h) {
Some(EntityType::MText(m)) => {
assert_eq!(m.style, "BIG", "MTEXT destination must take source style");
assert!(
(m.height - 5.0).abs() < 1e-9,
"MTEXT destination must take source height, got {}",
m.height
);
}
other => panic!("dest MTEXT missing: {other:?}"),
}
}
#[test]
fn handing_over_an_already_open_drawing_switches_to_its_tab() {
// Double-clicking a drawing that is already open should land on the tab
+26
View File
@@ -793,6 +793,19 @@ impl OpenCADStudio {
c.line_weight,
)
});
// Text-specific properties travel between text-like objects
// (TEXT ↔ MTEXT, both directions), like AutoCAD's "Text"
// special property (#361).
let text_props =
self.tabs[i]
.scene
.document
.get_entity(src)
.and_then(|e| match e {
acadrust::EntityType::Text(t) => Some((t.style.clone(), t.height)),
acadrust::EntityType::MText(m) => Some((m.style.clone(), m.height)),
_ => None,
});
if let Some((layer, color, linetype, lt_scale, lw)) = props {
self.push_undo_snapshot(i, "MATCHPROP");
@@ -803,6 +816,19 @@ impl OpenCADStudio {
crate::scene::view::dispatch::apply_line_weight(e, lw);
e.common_mut().linetype = linetype.clone();
e.common_mut().linetype_scale = lt_scale;
if let Some((style, height)) = &text_props {
match e {
acadrust::EntityType::Text(t) => {
t.style = style.clone();
t.height = *height;
}
acadrust::EntityType::MText(m) => {
m.style = style.clone();
m.height = *height;
}
_ => {}
}
}
}
}
self.tabs[i].dirty = true;