I have a program where different URCapProgramNodes talk to each other. This is all good to set up when creating the nodes programatically. However, I cannot seem to figure out how to set up these references when the program is loaded. Since you cannot save a reference to a TreeNode or a ProgramNode into the DataModel, these references are lost when the user saves, and loads the program.
I have tried using the CreationContext
to see if the program is loaded or not, which works. However, since the root node is loaded first, before all the nodes further down the tree, the root node has no children when it is being created. I therefore cannot set up the references from the root node on creation. And since you cannot traverse up the structure tree, I cannot set up the references from the nodes further down the tree either.
I have also tried using the openView
method, in the root node, to set up the references there. This works. However, when loading a program, the root node is not focused. The “Robot Program” page is initially in focus. Therefore the user can click on any of the other subnodes. These subnodes depend on information in other nodes, and therefore they crash.
Ideally I would like a method in the root node contribution to be called once all the nodes are created.
For a better understanding: can you show how the program tree is ordered before saving your program and after loading?
I have two of these connections.
The first is a duplicate of the WaypointNode. I have created my own (for various reasons), and I would like to copy the functionality of adding and deleting waypoints to the Move node (which in my case is just a folder).
Therefore I have a folder that contains several of my custom waypoints. For the waypoints to be able to add more of itself into its parent’s tree, it needs the reference:
Code example
URCapProgramNode waypointProgramNode = nf.createURCapProgramNode(CustomWaypointProgramNodeService.class);
parent.insertChildBefore(programModel.getRootTreeNode(this), waypointProgramNode);
The parent here, is needed. When creating the nodes the first time, this is done by for example:
TreeNode parent = root.addChild(nf.createFolderNode().setName("Waypoints"));
URCapProgramNode waypointProgramNode = nf.createURCapProgramNode(CustomWaypointProgramNodeService.class);
parent.addChild(waypointProgramNode);
CustomWaypointProgramNodeContribution waypoint = (CustomWaypointProgramNodeContribution) waypointProgramNode.getAs(DummyInterface.class);
waypoint.setParent(parent);
The other case is when using these waypoints. I have another node that needs a reference to this waypoints folder, to see how many waypoints have been created. Upon creation, this is done in the same manner as above, where the parent is present in the local namespace, and set on the new contribution using a setWaypointsTreeNode
method.
Any help is much appreciated! The current work around is setting these references in the updateView
function of the root program node. But for this to work, the user has to actually click into the root node.
Edit
You mentioned after loading. After loading everything is set up correctly, but the references (set by the setParent
and setWaypointTreeNode
are gone. This probably because the tree structure is saved in another format, and recreated in methods outside my own.
Is that Node a child of your whole urcap or another independent node in the program tree? Can you Screenshot the tree?
Yes, it is a child of the root node. Here is the tree.
So the Waypoints (Start, via, stop) need a reference to Waypoints (a folder). And “Adjustment Waypoints” (a URCapProgramNode) needs access to the Waypoints folder.
I found another workaround.
First I register all the root contributions in a static contributions keeper, which just has a list of all the current root contributions. In the updateView
function og the nodes that need references, I can locally check if the references are set up. If they are not set up, I can call the static contribution keeper, and ask it to call the set-up method for all the root contributions that are registered.
Note that the contributions should ideally be deleted when the user deletes them. Although this is not trivial, this question notes that you can use generateScript
to check in the currently active contributions. The method is called when all nodes are green and the user presses either save or play. By having a ContributionKeeper.getInstance().checkIn(this)
in the root contribution, you can keep an updated list.
1 Like