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

@ -356,6 +356,14 @@ pub(super) struct OpenCADStudio {
modal_drag_last: Option<Point>,
/// True while the modal title bar is held (a drag is in progress).
modal_dragging: bool,
// ── Attribute editor dialog (ATTEDIT / double-click a block) ───────────
/// INSERT whose attributes the editor modal is editing (`None` = closed).
attr_editor_handle: Option<acadrust::Handle>,
/// Block name shown in the editor's title bar.
attr_editor_block: String,
/// Working copy of the block's attributes as `(tag, value)`, in the same
/// order as `Insert::attributes`. Edited live; written back on OK.
attr_editor_fields: Vec<(String, String)>,
/// Plugin ids the user turned off in the Plugin Manager. Disabled plugins
/// keep their manifest listed but drop their ribbon tab and command
/// dispatch. Persisted via [`settings::UserSettings::disabled_plugins`].
@ -944,6 +952,7 @@ pub enum ModalKind {
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
AssocPrompt,
PointStyle,
AttributeEditor,
}
/// Identifies a DimStyle field that can be edited in the dialog.
@ -1442,6 +1451,13 @@ pub enum Message {
AboutOpen,
/// Close whatever in-canvas modal dialog is open (Plan B).
CloseModal,
// ── Attribute editor dialog ───────────────────────────────────────────
/// Open the attribute editor for an INSERT (double-click / ATTEDIT).
AttrEditorOpen(acadrust::Handle),
/// Live edit of the attribute value at row `idx` in the editor dialog.
AttrEditorInput { idx: usize, value: String },
/// Apply every attribute edit to the block and close the dialog (OK).
AttrEditorOk,
/// Title-bar pressed: begin dragging the active modal.
ModalGrab,
/// Cursor moved while dragging the modal title bar.
@ -1914,6 +1930,9 @@ impl OpenCADStudio {
modal_offset: iced::Vector::ZERO,
modal_drag_last: None,
modal_dragging: false,
attr_editor_handle: None,
attr_editor_block: String::new(),
attr_editor_fields: Vec::new(),
disabled_plugins: rustc_hash::FxHashSet::default(),
external_plugins: Vec::new(),
loaded_plugin_ids: rustc_hash::FxHashSet::default(),