forked from 1b-agent/opencadstudio-upstream
review(#1627): one UPDATEFIELD, honest counts, safe field boxes, one-pass host redraw
- UPDATEFIELD stays the command main already had (Select objects, undo, locale strings); it now takes the PR's reach — a block reference's attributes and block definition, a table's cell texts — and reports the fields that really changed. The PR's second implementation and its duplicate registration are gone. - FIELDEVAL's range error goes through the locale catalog. - Field boxes: no slicing inside a character, one layout per multi-line attribute, and TEXT boxes scale about the annotative reference point like the glyphs do. Comment and indentation put back where they belong. - bump_text_hosts classifies every host in one pass over the drawing instead of scanning all layouts and blocks per host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
711799371a
commit
af75cf42a8
6 files changed
+180
-169
No files matched your search
+34
-40
@@ -542,60 +542,54 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
/// UPDATEFIELD: every field the objects host is evaluated again and its
|
||||
/// text written back. A table's fields are hosted by the cell texts of its
|
||||
/// drawing (its `*T` block); fields a table keeps without such a text are
|
||||
/// evaluated when drawn and are not counted here.
|
||||
/// text written back, whatever FIELDEVAL says. A block reference brings
|
||||
/// its attributes and the texts of its block definition; a table, the
|
||||
/// cell texts of its drawing (its `*T` block).
|
||||
fn update_fields(&mut self, i: usize, handles: &[Handle]) {
|
||||
let doc = &self.tabs[i].scene.document;
|
||||
let mut found = 0;
|
||||
let mut updates: Vec<(Handle, String)> = Vec::new();
|
||||
let mut hosts = handles.to_vec();
|
||||
for h in handles {
|
||||
let Some(entity) = doc.get_entity(*h) else { continue };
|
||||
let hosts: Vec<Handle> = match entity {
|
||||
EntityType::Table(t) => t
|
||||
let record = match doc.get_entity(*h) {
|
||||
Some(EntityType::Insert(insert)) => {
|
||||
hosts.extend(insert.attributes.iter().map(|a| a.common.handle));
|
||||
doc.block_records.get(&insert.block_name)
|
||||
}
|
||||
Some(EntityType::Table(t)) => t
|
||||
.block_record_handle
|
||||
.and_then(|r| doc.block_records.iter().find(|b| b.handle == r))
|
||||
.or_else(|| doc.block_records.get(&t.block_name).filter(|_| !t.block_name.is_empty()))
|
||||
.map(|record| record.entity_handles.clone())
|
||||
.unwrap_or_default(),
|
||||
_ => vec![*h],
|
||||
.or_else(|| doc.block_records.get(&t.block_name).filter(|_| !t.block_name.is_empty())),
|
||||
_ => None,
|
||||
};
|
||||
for host in hosts {
|
||||
if !doc.get_entity(host).is_some_and(|e| crate::entities::field::hosts_field(doc, e)) {
|
||||
continue;
|
||||
}
|
||||
found += 1;
|
||||
if let Some(text) = crate::entities::field::resolve(doc, host) {
|
||||
updates.push((host, text));
|
||||
}
|
||||
if let Some(record) = record {
|
||||
hosts.extend(record.entity_handles.iter().copied());
|
||||
}
|
||||
}
|
||||
let attributes: Vec<&codec::entities::EntityCommon> = handles
|
||||
.iter()
|
||||
.filter_map(|h| match doc.get_entity(*h) {
|
||||
Some(EntityType::Insert(insert)) => Some(insert.attributes.iter().map(|a| &a.common)),
|
||||
_ => None,
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
let found = hosts
|
||||
.iter()
|
||||
.filter(|h| match doc.get_entity(**h) {
|
||||
Some(entity) => crate::entities::field::hosts_field(doc, entity),
|
||||
None => attributes.iter().any(|common| {
|
||||
common.handle == **h && crate::entities::field::common_hosts_field(doc, common)
|
||||
}),
|
||||
})
|
||||
.count();
|
||||
self.command_line.push_output(&crate::tf!("{found} field(s) found."));
|
||||
if found == 0 {
|
||||
return;
|
||||
}
|
||||
self.push_undo_snapshot(i, "UPDATEFIELD");
|
||||
let mut changed = Vec::new();
|
||||
for (h, text) in updates {
|
||||
if let Some(entity) = self.tabs[i].scene.document.get_entity_mut(h) {
|
||||
match entity {
|
||||
EntityType::MText(m) => m.value = text,
|
||||
EntityType::Text(t) => t.value = text,
|
||||
EntityType::AttributeDefinition(a) => a.default_value = text,
|
||||
_ => continue,
|
||||
}
|
||||
changed.push((h, crate::scene::ChangeKind::Modified));
|
||||
}
|
||||
let updated = self.tabs[i].scene.update_fields(32, Some(&hosts));
|
||||
if updated > 0 {
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
let updated = changed.len();
|
||||
// Table cell texts live in a block definition.
|
||||
let scene = &mut self.tabs[i].scene;
|
||||
if scene.changes_touch_block_definition(&changed) {
|
||||
scene.bump_geometry();
|
||||
} else {
|
||||
scene.bump_entities(&changed);
|
||||
}
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line.push_output(&crate::tf!("{updated} field(s) updated."));
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user