How to select multiple items in a TTreeView in code - treeview

I'm trying to select all the child node of a parent node when the parent is clicked, but when I for each node set the Selected = true i only end up with the last one being selected.
MultiSelect is true and I can do it with the mouse, so the setup should be ok.
For testing I use this code:
TTreeNode *node = Tv->Items->GetFirstNode();
node->Selected = true;
node = node->GetNext();
node->Selected = true;
node = node->GetNext();
node->Selected = true;
node = node->GetNext();
node->Selected = true;
Any tricks to make this work?

The TTreeNode::Selected property does not support multiple selections when toggling the node's selection state. Internally, it will call the Win32 TreeView_SelectItem() API, which selects a single node only.
For multi-select, use the TTreeView::Select() method instead:
The select method selects one or more tree nodes.
That being said, your example is attempting to select (potentially) every node in the TreeView, not just the child nodes of a parent node, as you claim.
Try this:
void AddNodeAndChildrenToList(TList *List, TTreeNode *Node)
{
List->Add(Node);
TTreeNode *child = Node->getFirstChild();
while (child)
{
AddNodeAndChildrenToList(List, child);
child = child->getNextSibling();
}
}
...
TList *nodes = new TList;
try
{
TTreeNode *parent = ...;
AddNodeAndChildrenToList(nodes, parent);
Tv->Select(nodes);
}
__finally
{
delete nodes;
}

Related

JavaFX8: display an image as disclosure node for childless TreeViewItems

I have defined images for the two states of a disclosure node (collapse/expand) according to Change expand and collapse image TreeView JavaFX 2.2
But I would like to have a third image for folder nodes, which still haven't any children nodes. It should not possible to expand/collapse such nodes, but it should display an image too (i.e. a minus.png for expanded nodes, a plus.png for collapsed nodes and an empty rectangle for folder nodes without any children).
Is it possible?
Having no children means that tree item is leaf node with type of "folder". You can utilize graphic property of tree item to show "empty rectangle" image:
ImageView ivfolder = new ImageView( "path/to/empty_rectangle.png" );
// You may use bindings
treeitem.graphicProperty().bind( Bindings
.when( treeitem.leafProperty() )
.then( ivfolder )
.otherwise( ( ImageView ) null )
);
// or set explicitly for that tree item
TreeItem<Folder> item = new TreeItem<>( "<empty>", ivfolder );
Don't forget to create new imageviews for every treeitem added to treeView and which needs that image.
I have defined a css structure for the childless case:
.tree-cell:browser-folder-childless .tree-disclosure-node .arrow {
-fx-font-weight: bold;
-fx-shape: null;
-fx-background-color: null;
-fx-background-image: url("childless.png");
-fx-background-repeat: no-repeat;
}
.tree-cell:browser-folder-childless:expanded .tree-disclosure-node .arrow {
-fx-font-weight: bold;
-fx-shape: null;
-fx-background-color: null;
-fx-background-image: url("childless.png");
-fx-background-repeat: no-repeat;
}
Next I have extended the TreeItem class:
public class BrowserTreeItem extends TreeItem<MyData> {
public BrowserTreeItem(MyData data) {
super(data);
}
#Override
public boolean isLeaf() {
return (getValue().getTypes().contains(NodeType.FOLDER) && getValue().getChildren().size() == 0) ? false : super.isLeaf();
}
}
So the TreeItem returns always false for isLeaf() in the case of a childless folder. The isLeaf() method will be used by the com.sun.javafx.scene.control.skin.TreeCellSkin.class to decide, whether or not the disclosure node should be removed. Rebuilding the node could be tricky, so I prevent the remove of the node.
This results in a normal disclosure node, now I have to change the image of the node.
It would be nice to overwrite also the isExanded() method of the TreeItem class. Then I would need only one CSS structure (the method would return always false for childless folders). But isExpanded() is final. So I cannot prevent the not/expanded switch by the user and I have to define two CSS structures.
Next, I have built a TreeCellFactory, which generates my own BrowserTreeCell classes. It toggles a PseudoClass state, which we use in the CSS above to activate some new images for the disclosure node.
public class BrowserTreeCell extends TreeCell<MyData> {
private final PseudoClass childless = PseudoClass.getPseudoClass("browser-folder-childless");
#Override
protected void updateItem(MyData item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
setText(item.getName());
setGraphic(item.getThumbnail());
setTooltip(item.getTooltip());
} else {
setText("");
setGraphic(null);
setTooltip(null);
}
pseudoClassStateChanged(childless, !empty && item != null && item.getTypes().contains(NodeType.FOLDER) && item.getChildren().size() == 0);
}
}
As the result, I get a disclosure node with a "childless.png" in both cases (not/expanded).

Search an Element in D3 Force Layout

Base on Collapsible Tree Search, I was able to search an element using the force directed graph. The problem is when I choose a search name, it will only hightlight the element and its first level of parent. How to hightlight the links and the nodes from the search element to the root?
Here's my code on Plunker Search on Force Directed Graph.
function searchTree (d) {
if (d.children)
d.children.forEach(searchTree);
else if (d._children)
d._children.forEach(searchTree);
var searchFieldValue = eval(searchField);
if (searchFieldValue && searchFieldValue.match(searchText)) {
// Walk parent chain
var ancestors = [];
var parent = d;
while (typeof(parent) !== "undefined") {
ancestors.push(parent);
// console.log(parent);
parent.class = "found";
parent = parent.parent;
}
// console.log(ancestors);
}
}
I've already compared everything on how it was being implemented on a tree but I was not able to find it out why.

yui treeview dynamic loading

Can you please let me know how can I have 3rd level sub nodes in YUI treeview.
I know how to do it for first level sub nodes.
For example ,
for first level we have grandparents of family.
in the next level we have parents.
In the next we have grandchildren.
It works for me till second level.i.e first level sub nodes.
but for next level how should I set dynamic loading?
What I have done for first level sub nodes is associate callback to tree.
var tree=new YAHOO.widget.TreeView("tree");
var sUrl = "getJsonData-imp-ses";
var callback = {
success : function(oResponse) {
var array1 = YAHOO.lang.JSON.parse(oResponse.responseText);
if (YAHOO.lang.isArray(array1)) {
for (var i = 0, j = array1.length; i < j; i++) {
var tempNode = new YAHOO.widget.TextNode(array1[i], tree.getRoot(), false);
console.log(tempNode);
}
}
tree.draw();
},
failure : function(oResponse) {
},
timeout : 7000
};
YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
tree.setDynamicLoad(function(node,fnLoadComplete){
YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
callback={
success:{},
failure:{},timeout:700
};
)};
Now I want attach sub nodes to the 1st level sub nodes.
I am using YUI 2.9.0.
Can anyone please help?
See: http://yui.github.io/yui2/docs/yui_2.9.0_full/examples/treeview/dynamic_tree.html for a full example.
In your code, instead of using tree.getRoot() as the place to append the loaded nodes to, you can reference any other node to append them to, just like in the above example.

Allow only 8 selection in a Telerik radTreeListView

I have a radTreeListView with multiple parent nodes,which can contain multiple child nodes which can also contain multiple sub-child nodes.
I want to make sure only 8 items are selected and no more than that. Those 8 selections MUST also be under the same parent node.
You could try something like that:
private RadTreeNode GetParentNode(RadTreeNode currentNode) {
if (currentNode.Parent!=null) {
return GetParentNode(currentNode.Parent);
}
return currentNode;
}
private void CountSelectedNodes(RadTreeNode firstNode, ref int selectedCount) {
if (firstNode.Nodes!=null) {
foreach(RadTreeNode node in firstNode.Nodes) {
CountSelectedNodes(node, ref selectedCount);
}
if (firstNode.IsSelected) {
selectedCount+=1;
}
}
}
private bool SelectionAllowed(RadTreeNode currentNode) {
RadTreeNode treeNode=GetParentNode(currentNode);
int selectedCount;
CountSelectedNodes(treeNode, ref selectedCount);
return selectedCount<=8;
}
(this code is not tested so there could be some bugs)
Call selectionAllowed() with the Node currently clicked

How to remove a single child node in tree layout

This is for a tennis draw and I need to be able to have a bye, so most parents have two children, ie. winner of each match goes through, but in some cases there is a bye, so there is only one child. See here as an example where some parent matches have no children and some have one: http://www.irtpa.com/index.php/realtennis/ladder/1246
I don't think this answer helps: How to remove node on tree layout D3.js?
As it is assuming that ALL children of a node are hidden/removed.
I've got this far based on the above stackoverflow answer but my brain cannot see the solution for removing/hiding the child:
function check_children(data, parent) {
// recurse through array and toggle/hide any Match Byes
if (typeof data.data != "undefined") {
if (data.data.bye == "byeM") {
toggle(parent);
}
}
if (data.children) {
check_children(data.children[0], data);
check_children(data.children[1], data);
}
}
function toggle(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
}
If you want to remove your "bye" children I would probably test before recursing. So something like:
function removeByeChildren(parent) {
if(!parent.children)
return;
var i = 0;
while(i < parent.children.length) {
var data = parent.children[i].data;
if (typeof data != "undefined" && data.bye == "byeM") {
// remove child - could save it in _children if you wanted to ever put it back
var child = parent.children.splice(i,1);
// length of child list reduced, i points to the next child
}
else {
// not a bye - recurse
removeByeChildren(parent.children[i]);
// all the child's bye's are removed so go to the next child
i++;
}
}
}
You can play with it here. The idea is to check each child if it is a bye or not. If it is we remove it from the list and if it is not we recurse and remove all the descendant child byes.

Resources