I have used the below to rename the node but is their a way to avoid changing the position?
void rename(Node node, String newName) throws RepositoryException
{
node.getSession().move(node.getPath(), node.getParent().getPath() + "/" + newName);
node.getSession().save();
}
Nodes can be ordered if the parent node supports child node ordering. When you rename a node, you will need to move it back. Basically, get the parent node, ask for the child nodes, iterate over them until you find the node you want to come after this one, then call node.orderBefore(renamedNode, nextSibling).
Related
I'm using cytoscape.js and cytoscape.js-expand-collapse to create dynamic hierarchies in my graph structure. I would like to be able to dynamically create a collapsed(merged) node that could potentially be expanded out, removed or possibly re-merged with additional nodes. I am having trouble whenever I call nodes.move({parent:null}). They become detached from the graph and I cannot re-attach them to a new parentNode. If I call restore on them I will see errors saying they already exist in the graph.
merge and unmerge by itself works fine in a simple case of no existing collapsed nodes. However calling merge on something that already contains a compound collapsed node breaks things. I would get the resulting merged node without the children of the previously collapsed merge candidate
Update #1 I've realized my problem was returning the wrong moved nodes. Calling .move on a collection returns a new set of nodes. so the unmerge should return those instead.
Update #2 cytoscape-expand-collapse utility does some internal book-keeping during the parent node collapse/expand by tucking away node data in 'originalEnds' data prop on the meta edges. so, if I'm now altering the graph dynamically by moving nodes in/out of parents these originalEnds pointers get out of sync causing infinite loops. I am doing some additional node tracking of my own as a workaround.
function merge(nodes){
//if one of the nodes is a compound itself, first uncollapse, then merge
var collapsed = nodes.filter(function(c){return typeof c.data('collapsedChildren')!=='undefined';});
if (collapsed.length>0) {
// for now just assume collapsed is a length of 1
var unmerged = unmerge(collapsed); //unmerged should be now the former collapsed children
nodes = nodes.subtract(collapsed).union(unmerged.nodes());
}
var parentNode = cy.add({group:'nodes', data: {id: parentID}});
nodes.move({parent: parentID});
collapseApi.collapse(parentNode);
return parentNode;
}
function unmerge(parentNode){
collapseApi.expand(parentNode);
var children = parentNode.children();
var moved = children.move({parent:null});
//at this point children become "detached" from the graph
// .removed() returns true, however, calling restore() logs an error and they are still technically in the graph
parentNode.remove();
return moved;
}
ele.move() has a more convenient implementation in cytoscape>=3.4: The elements are modified in-place instead of creating replacement elements.
Old code that uses the returned collection from ele.move() will still work. New code can be simplified by not having to use the returned collections at all.
Problem:
In the screenshot below, I have a node 300-9885-00X along with its TreeNodeCollection (in the red square). A little bit lower, we find the 300-9885-00X again, I want to insert the TreeNodeCollection that we found earlier, into that node ...
Background Information
I have a recursive program that goes through AutoCAD / SolidEdge assemblies. It opens the documents and prints the assemblies, and their children, and so on (recursively) ...
Green color means it is printed
Orange means it has already been printed before, so we don't need to print it again...
Question:
How do we insert an existing TreeNodeCollection into a TreeNode?
Knowing:
The location of the TreeNodeCollection
The location of the node in which I want to insert the collection into
The following variable TreeNodes contains my collection. Must I loop through the collection in order to add its text?
You can't add a TreeNodeCollection to a Node. You must loop through the TreeNodeCollection and add the nodes individually like so:
For j As Integer = 0 To TreeNodes.Count - 1
n.Nodes.Add(TreeNodes(j).Clone())
Next
Notice I used .Clone(). This is due to the insertion of an already existing node. You can't do that, you must either delete the existing one or clone it. In my case, I had to clone it.
// Get the '_NodesCollection' from the '_parentNode' TreeNode.
TreeNodeCollection _Nodes = _parentNode.FirstNode.Nodes;
// Create an array of 'TreeNodes'.
TreeNode[] Nodes = new TreeNode[_Nodes.Count];
// Copy the tree nodes to the 'Nodes' array.
_Nodes.CopyTo(Nodes, 0);
// Remove the First Node & Children from the ParentNode.
_parentNode.Nodes.Remove(_parentNode.FirstNode);
// Remove all the tree nodes from the '_parentNode' TreeView.
_parentNode.Nodes.Clear();
// Add the 'Nodes' Array to the '_parentNode' ParentNode.
_parentNode.Nodes.AddRange(Nodes);
// Add the Child Nodes to the TreeView Control
TvMap.Nodes.Add(_parentNode);
So I have this Treeview to which I manually add some items.
Parent nodes can be added without problems, but when I want to add a child node to a parent node that I search by key, it fails for some reason.
This is the code:
tvConstantGroups.Nodes.Add("Boekhouding")
tvConstantGroups.Nodes("Boekhouding").Nodes.Add("Exact") 'These 2 lines fail
tvConstantGroups.Nodes("Boekhouding").Nodes.Add("BoB")
The error message that I am getting is that the node "Boekhouding" does not exist (NULL / Nothing)
tvConstantGroups.Nodes.Add("Boekhouding", "Boekhouding")
tvConstantGroups.Nodes("Boekhouding").Nodes.Add("Exact", "Exact")
tvConstantGroups.Nodes("Boekhouding").Nodes.Add("BoB", "Exact")
The first parameter of Nodes.Add is Text Not the Name of Node
I have a tree panel whose nodes are loaded dynamically from the server. When the user expands a node, it will load the children for that node from the server and add them to that node. This part is working.
When the user collapses a node, I'd like to remove all the children from that node and "reset" the node so that it can be exanded again.
So far, I have the following in the collapse event handler:
function(node){
node.removeAll(); // remove all child nodes
// this causes the expand arrow to disappear
node.expandable = true;
// ... now what?
}
How do I "reset" the node (the "... now what?") so that the view knows to add the expand arrow back again?
Essentially I'd like the process of collapsing and then re-expanding a node to reload all of the children under that node.
The solution is to set the loaded field to false. The "expanded" attribute does not need to be changed.
The final solution is:
function(node){
node.removeAll(); // remove all child nodes
node.set('loaded', false); // tell node it can be expanded again
}
I am new to libxml. I would like to write 1 loop to loop through all the children of a child node etc. e.g.
<par>i want to <bold>loop <italic>through </italic> all</bold> children in this node</par>
At the moment my looping code look as follows but I only get the "bold" node and not the "italic" child.
if (xmlStrEqual(node->name, BAD_CAST "p")) {
xmlNodePtr child = node->children;
while (child != NULL) {
child = child->next;
}
}
It is conceivable that the node structure could grow to 4-5 elements, so I need a solution which is more robust that putting while loops within while loops. Any help would be appreciated please.
The xmlTree interface you're using is heirarchical. <par> has 3 children - the text before <bold>, <bold> itself, and the text after. <bold> has children of its own, which includes <italic>. The node->children list only contains the immediate children of a node.
There are a couple ways to get the behavior that you want.
While processing child, you can recursively process child->children to get to <bold>'s child, which includes <italics>
If you're looking SPECIFICALLY for that <itallic> (or for a set of specific nodes), you can use an XPath expression, such as "par//italic" to find any italic node anywhere beneath par.
http://www.xmlsoft.org/examples/index.html#XPath
You could look at libxml2's xmlTextReader interface rather than this xmlTree. It provides the serial "read through" of the document that you're expecting.
http://xmlsoft.org/xmlreader.html
Each method has its own advantages/disadvantages, depending on what all you're trying to do with your application.