From 56c39f1c173e005ea5ccc04dc7fc829891a63d2e Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Sat, 10 Oct 2026 18:14:06 +0200 Subject: [PATCH] Keep ATTDEF prompt when saving DXF (#81) (#137) --- crates/io/src/dxf_write.rs | 14 +++++++------- crates/io/src/tests.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/crates/io/src/dxf_write.rs b/crates/io/src/dxf_write.rs index 4f672a1..6c48ec3 100644 --- a/crates/io/src/dxf_write.rs +++ b/crates/io/src/dxf_write.rs @@ -286,7 +286,7 @@ fn common_x(w: &mut W, e: &Entity, owner: &str, paper: bool, subclass: &str, ass } } -fn text_tags(w: &mut W, t: &Text, attrib_tag: Option<(&str, bool)>, attdef: bool) { +fn text_tags(w: &mut W, t: &Text, attrib_tag: Option<(&str, bool)>, attdef_prompt: Option<&str>) { w.p(10, t.insert); w.f(40, t.height); w.s(1, &t.value); @@ -322,9 +322,9 @@ fn text_tags(w: &mut W, t: &Text, attrib_tag: Option<(&str, bool)>, attdef: bool } match attrib_tag { Some((tag, invisible)) => { - w.s(100, if attdef { "AcDbAttributeDefinition" } else { "AcDbAttribute" }); - if attdef { - w.s(3, ""); + w.s(100, if attdef_prompt.is_some() { "AcDbAttributeDefinition" } else { "AcDbAttribute" }); + if let Some(prompt) = attdef_prompt { + w.s(3, prompt); } w.s(2, tag); w.i(70, i64::from(invisible)); @@ -454,12 +454,12 @@ fn entity(w: &mut W, d: &Drawing, e: &Entity, owner: &str, paper: bool, cx: &Ctx EntityKind::Text(t) => { w.s(0, "TEXT"); common(w, e, owner, paper, "AcDbText"); - text_tags(w, t, None, false); + text_tags(w, t, None, None); } EntityKind::AttDef(a) => { w.s(0, "ATTDEF"); common(w, e, owner, paper, "AcDbText"); - text_tags(w, &a.text, Some((&a.tag, a.invisible)), true); + text_tags(w, &a.text, Some((&a.tag, a.invisible)), Some(&a.prompt)); } EntityKind::MText(t) => { w.s(0, "MTEXT"); @@ -512,7 +512,7 @@ fn entity(w: &mut W, d: &Drawing, e: &Entity, owner: &str, paper: bool, cx: &Ctx w.s(100, "AcDbEntity"); w.s(8, &e.common.layer); w.s(100, "AcDbText"); - text_tags(w, &a.text, Some((&a.tag, a.invisible)), false); + text_tags(w, &a.text, Some((&a.tag, a.invisible)), None); } let sh = w.h(); w.s(0, "SEQEND"); diff --git a/crates/io/src/tests.rs b/crates/io/src/tests.rs index f8331b3..955da7f 100644 --- a/crates/io/src/tests.rs +++ b/crates/io/src/tests.rs @@ -865,3 +865,32 @@ fn mleader_is_written_as_leader_and_mtext() { assert!(back.model.iter().any(|e| matches!(e.kind, EntityKind::Leader(_)))); assert!(back.model.iter().any(|e| matches!(&e.kind, EntityKind::MText(t) if t.contents == "Note"))); } + +#[test] +fn attdef_prompt_survives_dxf_roundtrip() { + let mut d = Drawing::new_metric(); + let text = Text { + insert: Vec3::ZERO, + align_pt: None, + height: 2.0, + value: "X".into(), + rotation: 0.0, + width_factor: 1.0, + oblique: 0.0, + style: "Standard".into(), + halign: HAlign::Left, + valign: VAlign::Baseline, + }; + let attdef = |prompt: &str| { + EntityKind::AttDef(Attrib { tag: "TAG1".into(), text: text.clone(), invisible: false, constant: false, prompt: prompt.into() }) + }; + d.add(&Space::Model, Default::default(), attdef("Enter value")).unwrap(); + d.add(&Space::Model, Default::default(), attdef("")).unwrap(); + let back = roundtrip(&d); + let prompts: Vec<&str> = back + .model + .iter() + .filter_map(|e| if let EntityKind::AttDef(a) = &e.kind { Some(a.prompt.as_str()) } else { None }) + .collect(); + assert_eq!(prompts, vec!["Enter value", ""]); +}