feat(attedit): attribute editor dialog for blocks

Double-clicking a block reference that has attributes, or running ATTEDIT
on one, now opens an editor dialog listing every attribute (tag + editable
value) with OK / Cancel. OK writes the values back to the block, with undo
and a repaint; Cancel discards. A block with no attributes still enters
in-place block edit (REFEDIT) on double-click as before. (#192)

ATTEDIT opens the dialog directly when a suitable block is already
selected; otherwise it runs the pick command and the dialog opens once a
block is chosen. This replaces the earlier command-line, per-attribute
prompt flow, which is removed along with its __ATTEDIT__ sentinel path and
the now-unused attedit_set_attrs trait hook; the ATTEDIT command is reduced
to a plain block picker.

The dialog is a tab-scoped in-canvas modal (Plan B): its working copy holds
a document-local handle, so closing that tab or switching away dismisses the
editor rather than risk applying edits to another tab's document.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-07-01 08:05:25 +03:00
commit 86a59d6c7e
12 changed files with 346 additions and 192 deletions

View file

@ -2437,9 +2437,18 @@ pub(super) fn on_tick(&mut self, t: Instant) -> Task<Message> {
if is_editable_text {
return self.begin_text_edit(handle);
}
// Double-clicking a block reference enters in-place
// block edit (REFEDIT), so its geometry can be edited
// and the change reflects in every instance. (#136)
// Double-clicking a block with attributes opens the
// attribute editor (edit its values); a block with
// no attributes enters in-place block edit (REFEDIT),
// so its geometry can be edited and the change
// reflects in every instance. (#136, #192)
let insert_has_attrs = matches!(
self.tabs[i].scene.document.get_entity(handle),
Some(AcadEntityType::Insert(ins)) if !ins.attributes.is_empty()
);
if insert_has_attrs {
return Task::done(Message::AttrEditorOpen(handle));
}
let is_insert = matches!(
self.tabs[i].scene.document.get_entity(handle),
Some(AcadEntityType::Insert(_))