We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Right now I am having trouble getting the parent/child relationship working in my tree visualization. The problem comes where I am trying to get children to display, the childrens children to display, and make sure that all can be expanded and collapsed appropriately. (Should be able to expand node, expand it's child and their children, then be able to collapse each of those). I am getting lost in the logic, does anybody have some tips?
Main Sketch:
Node root;
Node current;
XML data;
void setup(){
root = new Node();
data = loadXML("nodes.xml");
size(750,750);
smooth(true);
background(255);
loadChild(root, data, null);
}
void loadChild(Node node, XML data, Node parent) {
/* LoadChild() pulls in XML, assigns titles, assigns types,
creates new nodes for children, and repeats until all nodes
are created. */
//------------------Title & Type-----------------------//
XML title = data.getChild("title");
XML type = data.getChild("type");
String xmlTitle = title.getContent();
String xmlType = type.getContent();
node.title = xmlTitle;
node.type = xmlType;
//----------------Create children----------------------//
XML[] XMLchildren = data.getChildren("child");
node.children = new Node[XMLchildren.length];
for(int i=0;i<XMLchildren.length;i++){
node.children[i] = new Node();
}
//---------------------DEBUG---------------------------//
println("Current Node: " + node.title);
if(parent!=null){
println("Parent: " + parent.title);
node.parent = parent;
}
if(node.children!=null){
println("Number of Children:" + XMLchildren.length);
}
if(node.type!=null){
println("Node Type: " + node.type);
}
println("");
//---------------------REPEAT--------------------------//
for (int i = 0; i < XMLchildren.length; i++) {
loadChild(node.children[i], XMLchildren[i], node);
}
}
void draw(){
//--------------------INITIALIZE-----------------------//
background(255);
root.display();
//-----------------DISPLAY CHILDREN--------------------//
if(root.collapsed == false) { // FIRST RUN FROM NODE
for (int i = 0; i < root.children.length; i++) {
root.children[i].display(); // FIRST TIER CHILDREN
}
}
}
void mousePressed(){
//--------------------INITIALIZE-----------------------//
root.clickedActive();
//---------------------CHILDREN------------------------//
for (int i = 0; i < current.children.length; i++) {
root.children[i].clickedActive();
}
}
Node Class:
/* @pjs font="Junction-light.otf"; */
PFont f;
class Node {
Node parent;
Node[] children;
public String title;
public String type;
int x=80;
int y=140;
int tWidth;
int tHeight;
int titleColor = 0;
float textSize=70;
public boolean active = false;
public boolean collapsed = true;
Node(){
f = createFont("Junction-light.otf",100,true);
textFont(f,textSize);
}
void display(){
/* Display() prints text, with the link color and
bounding box debug. */
if(parent == null) {
fill(titleColor);
text(title,x,y);
//-------------------DEBUG----------------------//
textFont(f,textSize/3);
if(active==true){text("Active",x*7,y);}
else if(active==false){text("Inactive",x*7,y);}
else{text("Undefined",x*5,y);}
if(collapsed==true){text("Collapsed",x*7,y-30);}
else if(collapsed==false){text("Expanded",x*7,y-30);}
else{text("Undefined",x*5,y-30);}
//----------------------------------------------//
textFont(f,textSize);
noFill();
} else if(parent.collapsed == true){
noFill();
noStroke();
text(title,x,y);
}else{
fill(titleColor);
text(title,x,y);
//-------------------DEBUG----------------------//
textFont(f,textSize/3);
if(active==true){text("Active",x*7,y);}
else if(active==false){text("Inactive",x*7,y);}
else{text("Undefined",x*5,y);}
if(collapsed==true){text("Collapsed",x*7,y-30);}
else if(collapsed==false){text("Expanded",x*7,y-30);}
else{text("Undefined",x*5,y-30);}
//----------------------------------------------//
textFont(f,textSize);
noFill();
}
tHeight = textAscent();
tWidth = textWidth(title)+8;
//rect(x,y-tHeight,tWidth,tHeight);
}
void displaySpecialTypeA(){
println("specialTypeA");
}
void displaySpecialTypeB(){
println("specialTypeB");
}
void displaySpecialTypeC(){
println("specialTypeC");
}
void clickedActive(){
/* First checks if click is within bounds. If in bounds, and is
not already active, set active and expand, else, set inactive
and collapse. */
if(mouseX > x && mouseX < x+tWidth && mouseY > y-tHeight && mouseY < y){
if(active == false){ //if already inactive (default)
titleColor = 140; //make gray
active = true; //set active
current = this; //set node as current
collapsed = false; //
expandChildren(); //
}else if(active == true){ //if already active
titleColor = 0; //make black
active = false; //set inactive
collapsed = true; //
collapseChildren(); //
}
}
}
void expandChildren(){
/* Expands all immediate children nodes. */
/* TEMPORARY: Distributes children. */
for (int i = 0; i < children.length; i++) {
//this.children[i].collapsed = false;
this.children[i].y = y + 150 + 150*i;
}
}
void collapseChildren(){
/* Collapses all immediate children nodes and makes inactive. */
for (int i = 0; i < children.length; i++) {
//this.children[i].collapsed = true;
this.children[i].active = false;
}
}
}
nodes.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<type></type>
<title>Modernism</title>
<description></description>
<image></image>
<child>
<type></type>
<title>Authors</title>
<description></description>
<image></image>
<child>
<type></type>
<title>Franz Kafka</title>
<description></description>
<image></image>
</child>
<child>
<type></type>
<title>Gertrude Stein</title>
<description></description>
<image></image>
</child>
<child>
<type></type>
<title>T.S. Eliot</title>
<description></description>
<image></image>
</child>
</child>
<child>
<type></type>
<title>History</title>
<description></description>
<image></image>
<child>
<type></type>
<title>Paris</title>
<description></description>
<image></image>
</child>
</child>
<child>
<type></type>
<title>Resources</title>
<description></description>
<image></image>
<child>
<type></type>
<title>Google it.</title>
<description></description>
<image></image>
</child>
</child>
</root>
Thanks
Answers
Are you working with a recursive structure to store the nodes?
I suppose I should be, this was just proposed to me from a friend:
to recursively handle the clickedActive() function. Is this along the right lines?