fix(layers): allocate real handles for new layers (#67)

New layers were added to the table with a NULL handle, and the first
patch used the non-advancing `next_handle()` getter, so two new layers
(or a layer and the next allocated object) shared one handle. The DWG
format is handle-based, so the collision dropped the layer on save;
DXF is name-based and survived, which is why a rename appeared to fix
it.

Allocate a unique advancing handle via `allocate_handle()` in LAYER NEW
(panel + command line) and on rename when the source handle is invalid.
Rename now also clones the whole record so colour/linetype/lineweight
are kept, not just the flags.

Adds DWG/DXF round-trip tests covering one and multiple new layers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-09 19:37:42 +03:00
commit 6520195220
3 changed files with 64 additions and 11 deletions

View file

@ -403,3 +403,44 @@ fn fix_dxf_dimension_rotations(doc: &mut CadDocument) {
}
}
}
#[cfg(test)]
mod layer_roundtrip_tests {
use super::*;
use acadrust::tables::layer::Layer as DocLayer;
// Add `count` new layers the way the UI does (allocate_handle, then add),
// round-trip through `ext`, and return whether every one survived.
fn roundtrip_layers(ext: &str, count: usize) -> bool {
let mut doc = CadDocument::new();
crate::linetypes::populate_document(&mut doc);
let names: Vec<String> = (0..count).map(|n| format!("Layer{}", n + 1)).collect();
for name in &names {
let mut dl = DocLayer::new(name);
dl.handle = doc.allocate_handle();
doc.layers.add(dl).unwrap();
}
let path = std::env::temp_dir().join(format!("ocs_layer_rt_{count}.{ext}"));
save_as_version(&doc, &path, acadrust::DxfVersion::AC1032).expect("save");
let loaded = load_file(&path).expect("load");
let _ = std::fs::remove_file(&path);
names.iter().all(|n| loaded.layers.contains(n))
}
#[test]
fn dwg_preserves_new_layer() {
assert!(roundtrip_layers("dwg", 1), "DWG dropped the new layer (issue #67)");
}
#[test]
fn dxf_preserves_new_layer() {
assert!(roundtrip_layers("dxf", 1), "DXF dropped the new layer");
}
// Each new layer must get a distinct handle, or they collide and all but
// the last are dropped on a handle-based DWG save (issue #67).
#[test]
fn dwg_preserves_multiple_new_layers() {
assert!(roundtrip_layers("dwg", 3), "DWG dropped colliding new layers (issue #67)");
}
}