SonyWWS/ATF

Generating a DomNode with a unique ID and undo/redo

Closed this issue · 5 comments

Hello,

I am trying to generate a DomNode by using a context menu on a group, and I am having trouble with generating a unique ID.

First Method:

  • assign node to an object array (needed for instancingContext.CanInsert())
  • do transaction with instancingContext.Insert()

This method creates an extra node with a unique ID and leaves my original node with the default ID. This method also adds my transaction to the History (although I am uncertain how to implement undo/redo at the moment).

Second Method:

CategoryUniqueIdValidator uniqueIdValidator = childNode.GetRoot().Cast(); uniqueIdValidator.NameNode(childNode);

This method does give a unique name and keeps my child node with the correct properties; however, it does not show up in the History (which I guess means it cannot use undo/redo). Also, this method requires me to make NameNode public.

Is there a way to get the unique ID along with the History :)

Thanks.

For the first method, I am not sure there is a bug here.

I assume instancingContext is a subclass of ATF's CircuitEditingContext here.
CircuitEditingContext.Insert() actually does not insert the passed-in objects directly; it makes a deep copy of the passed-in objects first via DomNode.Copy, then inserts those COPIED DomNodes into the Dom tree. Undo/redo is automatically supported for DOM tree editings that are wrapped in a transaction; usually you don't need to write any code for undo/redo to work.

The unique naming mechanism is kicked in near the end of transaction, and it will check & fix name uniqueness only for those DomNodes that are in the (document) Dom tree, that's why the extra nodes( ie. copied nodes) have unique names because they are the nodes inserted to the dom tree. It seems your original node is not linked into the Dom tree. Perhaps you create a DomNode from scratch, where its parent is not set, so it is a dangling node. If you pass this node to Insert() method, this original node will be cloned to the extra node. But since the original node is not linked into the dom tree, it's name remains to be the default value.

For the second method, I don't see the necessity to increase the accessibility of CategoryUniqueIdValidator.NameNode(), which is private now. NameNode() is called AddNodes(), the latter is in turned called OnEnding() when a transaction is ending. Both UniqueIdValidator & CategoryUniqueIdValidator , once set up, automatically correct names at the end of a transaction. If you need explicitly call NameNode(), that means you are likely adding DomNode outside a transaction, which is very rare, and lost undo/redo for any Dom edits outside a transaction .

Typical code snippet to warp you dom edits inside a transaction:

var transactionContext =
contextRegistry.ActiveContext.As();
transactionContext.DoTransaction(() => { your code of inserting dom node}

The issue I had was caused by calling my custom "insert" (outside of DoTransaction) and then calling instancingContext.Insert in DoTransaction, thus generating two DomNode inserts. After looking at your code snippet, I just called my custom "insert" function in DoTransaction, which fixed the issue. Thanks :)

Cool! I think the reason that we make a copy first before insert, is that sometimes copy/paste may come from clipboard, or even another document. Copy-before-insert makes everything simpler. :-)