forked from 1b-agent/opencadstudio-upstream
fix(plugin): join plugin-opened undo scopes in XRecord writes
The internal per-call push_undo fractured plugin-composed operations: history has no nested scopes, so each push finished the plugin's still-pending scope and opened its own — an operation of several writes became several undo steps and the plugin's label was lost (measured: 3 creates + update + delete in one scope = 5 steps). Follow the entity-write contract instead: a mutation inside a plugin-opened push_undo scope joins it, so the whole operation is a single undo step under the plugin's label; a scope-less mutation opens and finishes its own scope, keeping one undo step per call; refusals record no undo step in either regime. Document the contract on the trait methods and the host docs; the composition experiment becomes the permanent xrecord_writes_join_a_plugin_initiated_undo_scope test.
This commit is contained in:
1 parent
ca2f0c9857
commit
297a4d3074
4 files changed
+166
-17
No files matched your search
@@ -1100,7 +1100,13 @@ pub trait HostApi {
|
||||
/// case-insensitive like dictionary lookups) happens **before** any change,
|
||||
/// so a failure leaves the drawing untouched. The record is registered in
|
||||
/// its dictionary and owned by it; the returned handle stays stable across
|
||||
/// updates. The change is one undo step.
|
||||
/// updates.
|
||||
///
|
||||
/// Undo composition — the entity-write contract: a mutation performed
|
||||
/// inside a plugin-opened [`HostApi::push_undo`] scope joins that scope,
|
||||
/// so an operation composed of several writes (entities and XRecords) is
|
||||
/// a single undo step under the plugin's own label. With no scope open
|
||||
/// the change is one undo step of its own. Refusals record no undo step.
|
||||
fn create_xrecord(
|
||||
&mut self,
|
||||
_dictionary_path: &[&str],
|
||||
@@ -1131,8 +1137,11 @@ pub trait HostApi {
|
||||
/// create anything silently. Identity (handle, owning dictionary) stays;
|
||||
/// the entries and their DWG handle-reference stream are replaced and the
|
||||
/// record's verbatim raw payloads are dropped, so subsequent saves emit the
|
||||
/// new content. A refusal leaves the drawing untouched; a successful change
|
||||
/// is one undo step whose undo restores the previous entries byte-exactly.
|
||||
/// new content. A refusal leaves the drawing untouched. Undo composition —
|
||||
/// the entity-write contract: a mutation inside a plugin-opened
|
||||
/// [`HostApi::push_undo`] scope joins that scope; with no scope open it is
|
||||
/// one undo step of its own, whose undo restores the previous entries
|
||||
/// byte-exactly. Refusals record no undo step.
|
||||
fn update_xrecord(
|
||||
&mut self,
|
||||
_dictionary_path: &[&str],
|
||||
@@ -1144,8 +1153,10 @@ pub trait HostApi {
|
||||
|
||||
/// Delete the XRecord named `name` and its dictionary entry (API v8,
|
||||
/// additive). Returns the removed record, so audits keep the prior
|
||||
/// content. A refusal leaves the drawing untouched; a successful delete is
|
||||
/// one undo step.
|
||||
/// content. A refusal leaves the drawing untouched. Undo composition — the
|
||||
/// entity-write contract: a mutation inside a plugin-opened
|
||||
/// [`HostApi::push_undo`] scope joins that scope; with no scope open it is
|
||||
/// one undo step of its own. Refusals record no undo step.
|
||||
fn delete_xrecord(
|
||||
&mut self,
|
||||
_dictionary_path: &[&str],
|
||||
|
||||
Reference in new issue
Block a user