Universal Robots Forum

UndoableChange and UndoRedoManager with HTML program node

I need to update DataModel in an HTML program node inside of a timer task that checks the state of a daemon.
If i try to set a parameter to DataModel i get the following error:
java.lang.IllegalStateException: Modifications to program tree and/or data model must be inside a 'UndoableChange' scope. Use 'UndoRedoManager' to group undoable changes.

I found that UndoRedoManager is specific for swing program nodes and so I’m not able to go further with application.
Is there any workaround? Is this a bug or it will never be possible to change DataModel in an HTML node using timer or threads?

When having a URCap in HTML, PolyScope calls into the URCap code using the annotated callbacks, when a user interacts with a program node.
Before calling the annotated callback in the URCap Contribution, PolyScope buffers the DataModel for the node.
When the callback returns, the updated DataModel is compared to the old one.
Any changes happened to the DataModel within this time, will be grouped into one “Undoable Action” and will be placed on the Undo Stack.
In that sense, PolyScope handles the View-domain and UndoRedoManager for you automatically, by using HTML.

In Swing, the complete interaction between View and Contribution happens inside the URCap itself.
Therefore PolyScope does not have the ability to check what changes should be grouped together as a single Undoable Action.
That is why the UndoRedoManager has been added to the Swing framework, so the URCap can group related changes as a single undoable change.

The reason for grouping the changes is, that one single user interaction, could potentially cause multiple changes to the DataModel.
If the changes are not grouped, this can cause an inconsistent state, when the user clicks “Undo” or “Redo” buttons in PolyScope.

From PolyScope 3.6 and 5.0, we will now throw an exception, if the DataModel is altered outside of the scope of either of the two scenarios mentioned above.
If the DataModel is changes asynchronously, and the user clicks undo, this could revert the last value from the DataModel. And would cause odd, and in-transparent issues to the user.

Note, that all of the above is only applicable to Program Nodes.
Since Installation domain is not covered by Undo-Redo functionality, this restriction does not apply to Installation Nodes.

A worksround for your issue could be to use the Installation Node to perform this check, where the program nodes can later call this value from the Installation nodes DataModel, to check the value there.
It also alleviates you from having to do this check for each node in the program, but only one time in the Installation node.

2 Likes

Is there a way to group the changes to the data model for the program nodes programatically if I’m not using swing? I need to be able to update the options in a dropdown menu based on messages coming via TCP/IP, which potentially can affect the data model if the option selected by the user was deleted, and I’d prefer not to store that information in the installation node.

How about not changing the DataModel, based on this input. But merely checking if the value saved in the DataModel, is no longer active, and hence setting a local variable, that is used by isDefined().
When the user navigates to the node, you can show that “this value was selected, but is no longer available”, and let the user deliberately change the

1 Like

Thanks for the answer; I was evaluating to implement something similar :slight_smile:

The fact that you also proposed it means that it’s probably the way to go.