141 lines
6.6 KiB
Rust
141 lines
6.6 KiB
Rust
//! `blocks.dynamic` and `blocks.list` report a dynamic block's parameters and actions as read
|
|
//! from another program's file (kept foreign data, built by hand here).
|
|
|
|
use std::sync::Arc;
|
|
|
|
use cadcraft_engine::Session;
|
|
use cadcraft_engine::doc::foreign::{Foreign, ForeignExtra, ForeignObject};
|
|
use cadcraft_engine::doc::{Handle, RawTag};
|
|
use serde_json::json;
|
|
|
|
fn obj(handle: u64, kind: &str, tags: &[(i32, &str)]) -> ForeignObject {
|
|
ForeignObject { handle: Handle(handle), kind: kind.into(), tags: tags.iter().map(|(c, v)| RawTag { code: *c, value: (*v).into() }).collect() }
|
|
}
|
|
|
|
/// A session whose block "Door" has a visibility parameter with two states.
|
|
fn session() -> Session {
|
|
let mut s = Session::new();
|
|
let l = s.execute("line", &json!({ "points": [[0, 0], [1, 0]] })).unwrap()["handles"][0].clone();
|
|
s.execute("block", &json!({ "name": "Door", "base": [0, 0], "handles": [l] })).unwrap();
|
|
let line = s.doc().unwrap().block("Door").unwrap().entities.handles()[0].hex();
|
|
let mut f = Foreign::default();
|
|
f.records.insert(("BLOCK_RECORD".into(), "DOOR".into()), ForeignExtra { xdict: Some(Handle(0xF00)), ..Default::default() });
|
|
f.objects.push(obj(0xF00, "DICTIONARY", &[(100, "AcDbDictionary"), (3, "ACAD_ENHANCEDBLOCK"), (360, "F01")]));
|
|
f.objects.push(obj(0xF01, "ACAD_EVALUATION_GRAPH", &[(100, "AcDbEvalGraph"), (91, "0"), (95, "1"), (360, "F02")]));
|
|
f.objects.push(obj(
|
|
0xF02,
|
|
"BLOCKVISIBILITYPARAMETER",
|
|
&[
|
|
(100, "AcDbEvalExpr"),
|
|
(90, "1"),
|
|
(100, "AcDbBlockElement"),
|
|
(300, "Visibility State"),
|
|
(100, "AcDbBlockParameter"),
|
|
(280, "1"),
|
|
(100, "AcDbBlock1PtParameter"),
|
|
(1010, "2"),
|
|
(1020, "3"),
|
|
(100, "AcDbBlockVisibilityParameter"),
|
|
(301, "Visibility1"),
|
|
(302, ""),
|
|
(93, "1"),
|
|
(331, &line),
|
|
(92, "2"),
|
|
(303, "Open"),
|
|
(94, "1"),
|
|
(332, &line),
|
|
(95, "0"),
|
|
(303, "Closed"),
|
|
(94, "0"),
|
|
(95, "0"),
|
|
],
|
|
));
|
|
let mut d = s.doc().unwrap().clone();
|
|
d.foreign = Arc::new(f);
|
|
s.open_drawing(d, "dynamic", None);
|
|
s
|
|
}
|
|
|
|
#[test]
|
|
fn dynamic_block_data_is_reported() {
|
|
let mut s = session();
|
|
let list = s.execute("blocks.list", &json!({})).unwrap();
|
|
let flags: Vec<_> = list["blocks"].as_array().unwrap().iter().map(|b| (b["name"].as_str().unwrap().to_string(), b["dynamic"].clone())).collect();
|
|
assert!(flags.contains(&("Door".into(), json!(true))), "{flags:?}");
|
|
|
|
let m = s.execute("blocks.dynamic", &json!({ "name": "DOOR" })).unwrap();
|
|
let p = &m["parameters"][0];
|
|
assert_eq!((p["node"].clone(), p["element"].clone(), p["showProperties"].clone()), (json!(1), json!("Visibility State"), json!(true)));
|
|
assert_eq!(p["kind"]["type"], "visibility");
|
|
assert_eq!(p["kind"]["label"], "Visibility1");
|
|
assert_eq!(p["kind"]["at"], json!({ "x": 2.0, "y": 3.0, "z": 0.0 }));
|
|
let states: Vec<_> =
|
|
p["kind"]["states"].as_array().unwrap().iter().map(|st| (st["name"].clone(), st["visible"].as_array().unwrap().len())).collect();
|
|
assert_eq!(states, [(json!("Open"), 1), (json!("Closed"), 0)]);
|
|
assert!(p["kind"]["controlled"][0].is_string(), "handles are hex strings");
|
|
assert_eq!(m["actions"], json!([]));
|
|
}
|
|
|
|
#[test]
|
|
fn blocks_without_dynamic_data_and_bad_names() {
|
|
let mut s = session();
|
|
let l = s.execute("line", &json!({ "points": [[0, 0], [1, 1]] })).unwrap()["handles"][0].clone();
|
|
s.execute("block", &json!({ "name": "Window", "base": [0, 0], "handles": [l] })).unwrap();
|
|
assert_eq!(s.execute("blocks.dynamic", &json!({ "name": "Window" })).unwrap(), json!(null));
|
|
assert_eq!(s.execute("blocks.dynamic", &json!({ "name": "*Model_Space" })).unwrap(), json!(null));
|
|
for p in [json!({}), json!({ "name": 3 }), json!({ "name": "Nope" }), json!(null)] {
|
|
assert!(s.execute("blocks.dynamic", &p).is_err(), "{p}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn a_reference_to_a_dynamic_block_reports_its_custom_properties() {
|
|
let mut s = session();
|
|
// BLOCK made the line a reference to Door, which has Door's own values.
|
|
let insert = s.doc().unwrap().model.handles()[0].hex();
|
|
let r = s.execute("blocks.reference", &json!({ "handle": insert })).unwrap();
|
|
assert_eq!(r["definition"], "Door");
|
|
assert_eq!(r["values"], json!({}));
|
|
assert_eq!(r["properties"], json!([{ "name": "Visibility1", "value": "Open", "choices": ["Open", "Closed"], "editable": true }]));
|
|
|
|
// A plain block's reference, objects that aren't references and bad parameters.
|
|
let l = s.execute("line", &json!({ "points": [[0, 0], [1, 1]] })).unwrap()["handles"][0].clone();
|
|
let plain = s.execute("block", &json!({ "name": "Window", "base": [0, 0], "handles": [l.clone()] })).unwrap()["insert"].clone();
|
|
assert_eq!(s.execute("blocks.reference", &json!({ "handle": plain })).unwrap(), json!(null));
|
|
let l = s.execute("line", &json!({ "points": [[0, 0], [2, 2]] })).unwrap()["handles"][0].clone();
|
|
assert!(s.execute("blocks.reference", &json!({ "handle": l })).is_err());
|
|
for p in [json!({}), json!({ "handle": "zz" }), json!({ "handle": "FFFFFF" }), json!(null)] {
|
|
assert!(s.execute("blocks.reference", &p).is_err(), "{p}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn a_visibility_state_is_changed_in_one_undo_step() {
|
|
let mut s = session();
|
|
let insert = s.doc().unwrap().model.handles()[0].hex();
|
|
let r = s.execute("blocks.reference.set", &json!({ "handle": insert, "name": "Visibility1", "value": "Closed" })).unwrap();
|
|
assert_eq!(r["properties"][0]["value"], "Closed");
|
|
let block = |s: &Session| match s.doc().unwrap().model.iter().next().map(|e| e.kind.clone()) {
|
|
Some(cadcraft_engine::doc::EntityKind::Insert(i)) => i.block,
|
|
other => panic!("{other:?}"),
|
|
};
|
|
assert!(block(&s).starts_with("*U"));
|
|
// Still a reference to Door, in its new state.
|
|
let r = s.execute("blocks.reference", &json!({ "handle": insert })).unwrap();
|
|
assert_eq!((r["definition"].clone(), r["properties"][0]["value"].clone()), (json!("Door"), json!("Closed")));
|
|
|
|
s.execute("undo", &json!({})).unwrap();
|
|
assert_eq!(block(&s), "Door");
|
|
let r = s.execute("blocks.reference", &json!({ "handle": insert })).unwrap();
|
|
assert_eq!(r["properties"][0]["value"], "Open");
|
|
|
|
for p in [
|
|
json!({ "handle": insert, "name": "Visibility1", "value": "Ajar" }),
|
|
json!({ "handle": insert, "name": "Visibility1" }),
|
|
json!({ "name": "Visibility1", "value": "Open" }),
|
|
json!({ "handle": insert, "value": "Open" }),
|
|
] {
|
|
assert!(s.execute("blocks.reference.set", &p).is_err(), "{p}");
|
|
}
|
|
}
|