// Inputs
void keyPressed() {
if (key == CODED) {
// CODED ------------------------------------------------
EvluateCodedKeys();
}
else {
// not Coded --------------------------------------
EvluateNotCodedKeys();
} // else
} // func
// ==============================================================
void EvluateCodedKeys () {
// coded
if (keyCode == UP) {
// move selection up
done=false;
int i2 = getSelectedNode () ;
//myTree[i].boolIsSelected = false;
int i = getNumberOfSelectedNodeInTree();
increaseSelectedNodeForMinus ( i - 1 ) ;
myTree[i2].boolIsSelected = false;
// if not done, it's at the beginning
if (!done) {
// at the beginning: go to End
increaseSelectedNode ( maxNumber-2 ) ;
}
} //
else if (keyCode == DOWN) {
// move selection down
done=false;
int i = getNumberOfSelectedNodeInTree();
print(i);
increaseSelectedNode ( i + 1 ) ;
// if not done
if (!done) {
// at the end: jump to the beginning
increaseSelectedNode ( 0 ) ;
}
i = getNumberOfSelectedNodeInTree();
println("---" + i);
// myTree[i].boolIsSelected = false;
} //
else
{
// do nothing
} // else
}
// ------------------------------------------------
void EvluateNotCodedKeys () {
if (key == '+') {
// extend branch
// println ("+");
int i = getSelectedNode ();
myTree[i].boolIsOpen = true; // open node
}
else if (key == '-') {
// hide branch
// println ("-");
int i = getSelectedNode ();
myTree[i].boolIsOpen = false;
}
else if (key == 'f') {
// flat text or not
boolShowAllTextAsFlatText=!boolShowAllTextAsFlatText;
}
else if (key == '0') {
// ZERO
int i = getSelectedNode () ;
myTree[i].boolIsSelected=false;
myTree[0].boolIsSelected=true;
// increaseSelectedNode ( 0 ) ;
}
else {
// do nothing
} // else
} // func
// output full graphic, Tree
void graphShowContentAsTree () {
// graphic with a nice indent
int currentX=-1;
// currentY=0;
currentNumber=1;
// chose the way of text representation (textMode):
if (boolShowAllTextAsFlatText) {
textMode (SCREEN);
currentX=10;
currentY=18;
}
else
{
textMode(MODEL);
currentX=-210;
currentY=-200;
} // else
// search tree for roots (can be one or more)
for (int i=0;i<myTree.length;i++) {
// when root
if (myTree[i].parentID==-1) {
// then Output
OutputTextWithParameters(i, currentX, currentY, 0);
// text ( myTree[i].showContentAsString(), currentX, currentY );
currentY = currentY + 18;
currentNumber++;
if (myTree[i].boolIsOpen) {
// show children
graphShowChildren (i, 1, currentX, currentY, 1 );
} // if
} // if
} // for
//
maxNumber= currentNumber;
/*
if (boolShowAllTextAsFlatText) {
maxNumber=int(currentY/18);
}
else {
maxNumber=int(currentY+200/18);
} // else
*/
} // func
void graphShowChildren ( int actualParent, int depth, int x, int y, int z ) {
// recursive
for (int i=0;i<myTree.length;i++) {
if (myTree[i].parentID==actualParent) {
OutputTextWithParameters(i, x + 9 * depth, currentY, z);
// next line
currentY = currentY + 18;
currentNumber++;
// when open
if (myTree[i].boolIsOpen) {
// recursive call
graphShowChildren ( i, depth+1, x+10, 100, depth * 30 );
}
} // if
} // for
} // func
void OutputTextWithParameters(int i, int x, int y, int z) {
String textToDisplay = "";
// color according to selection
if (myTree[i].boolIsSelected) {
fill (color (0, 210, 210));
indexOfTheSelectedNode=i;
}
else {
fill (color (((z+8)*20), 30, 10));
}
// get text to display
textToDisplay = myTree[i].strName ;
// when not open, append "(+)"
if (!myTree[i].boolIsOpen) {
textToDisplay = textToDisplay + " (+)";
}
// write graphical text "textToDisplay" at x,y,z
text ( textToDisplay, x, y, z );
} // func
// output as text only -> direct window
// ============================================================
// only Text, linear
void showContentLinear () {
// only testing (not a tree)
for (int i=0; i<myTree.length; i++) {
println ( myTree[i].showContentAsString() );
}
}
// ============================================================
// only Text, Tree
void showContentAsTree () {
// nice indent
for (int i=0; i<myTree.length; i++) {
if (myTree[i].parentID==-1) {
println ( myTree[i].showContentAsString() );
showChildren (i, 1);
} // if
} // for
} // func
void showChildren ( int actualParent, int depth ) {
// recursive
for (int i=0; i<myTree.length; i++) {
if (myTree[i].parentID==actualParent) {
println ( getIndent ( depth ) + myTree[i].showContentAsString() );
showChildren (i, depth+1);
} // if
} // for
} // func
String getIndent ( int depth ) {
// returns as many tabs as necessary for the "depth" of the node
String myIndent = "";
for (int i=0; i<depth; i++) {
myIndent=myIndent + char(9);
}
return (myIndent) ;
} // func
// Minor Tools
int getSelectedNode () {
// returns index for usage with myTree[i].boolIsSelected = false; etc.
return(indexOfTheSelectedNode);
/*
for (int i=0;i<myTree.length;i++) {
if (myTree[i].boolIsSelected) {
return(i);
} // if
} // for
return (-1);
*/
} // func
// =============================================================
void increaseSelectedNode ( int gotoNode ) {
for (int i=0;i<myTree.length;i++) {
if (myTree[i].parentID==-1) {
// delete old selection
if (myTree[i].boolIsSelected) {
// un-select
if (!done) {
myTree[i].boolIsSelected = false;
}
}
currentElement=0;
if (currentElement == gotoNode) {
myTree[i].boolIsSelected=true;
done=true;
}
increaseSelectedNodeChildren (i, gotoNode );
} // if
} // for
} // func
void increaseSelectedNodeChildren ( int actualParent, int gotoNode ) {
// recursive
// search children in the whole tree
for (int i=0;i<myTree.length;i++) {
// when it is a child
if (myTree[i].parentID==actualParent) {
// delete old selection
if (myTree[i].boolIsSelected) {
// un-select
if (!done) {
myTree[i].boolIsSelected = false;
}
}
currentElement = currentElement + 1;
if (currentElement == gotoNode) {
myTree[i].boolIsSelected=true;
done=true;
}
// when open
if (myTree[i].boolIsOpen) {
// recursive call: search childs children
increaseSelectedNodeChildren ( i, gotoNode );
}
} // if
} // for
} // func
// ============================================================
void increaseSelectedNodeForMinus ( int gotoNode ) {
for (int i=0;i<myTree.length;i++) {
if (myTree[i].parentID==-1) {
// delete old selection
if (myTree[i].boolIsSelected) {
// un-select
if (!done) {
//myTree[i].boolIsSelected = false;
}
}
currentElement=0;
if (currentElement == gotoNode) {
myTree[i].boolIsSelected=true;
done=true;
}
increaseSelectedNodeChildren (i, gotoNode );
} // if
} // for
} // func
void increaseSelectedNodeChildrenForMinus ( int actualParent, int gotoNode ) {
// recursive
// search children in the whole tree
for (int i=0;i<myTree.length;i++) {
// when it is a child
if (myTree[i].parentID==actualParent) {
// delete old selection
if (myTree[i].boolIsSelected) {
// un-select
if (!done) {
//myTree[i].boolIsSelected = false;
}
}
currentElement = currentElement + 1;
if (currentElement == gotoNode) {
myTree[i].boolIsSelected=true;
done=true;
}
// when open
if (myTree[i].boolIsOpen) {
// recursive call: search childs children
increaseSelectedNodeChildren ( i, gotoNode );
}
} // if
} // for
} // func
// ============================================================
int getNumberOfSelectedNodeInTree () {
currentElement=0;
for (int i=0; i<myTree.length; i++) {
if (myTree[i].parentID==-1) {
if (myTree[i].boolIsSelected) {
NumberOfSelectedNodeInTree = currentElement;
}
currentElement=1;
getNumberOfSelectedNodeInTreeChildren (i);
} // if
} // for
return (NumberOfSelectedNodeInTree);
} // func
void getNumberOfSelectedNodeInTreeChildren ( int actualParent ) {
// recursive
for (int i=0;i<myTree.length;i++) {
if (myTree[i].parentID==actualParent) {
if (myTree[i].boolIsSelected) {
NumberOfSelectedNodeInTree = currentElement;
}
currentElement = currentElement + 1;
// when open
if (myTree[i].boolIsOpen) {
// recursive call
getNumberOfSelectedNodeInTreeChildren ( i );
}
} // if
} // for
} // func
// MAIN
import peasy.*;
//import processing.opengl.*;
PeasyCam pCamera;
PFont font;
classNode[] myTree = new classNode[18];
boolean boolShowAllTextAsFlatText = true;
int currentY = 0;
// returns index for usage with myTree[i].boolIsSelected = false; etc.
int indexOfTheSelectedNode=-1;
int currentElement = -1;
int NumberOfSelectedNodeInTree = -1;
int currentNumber = -1;
int maxNumber = -1;
boolean done = false;
// ====================================================================
void setup () {
// Init
size (800, 800, P3D); // P3D
pCamera = new PeasyCam(this, 400);
// font = createFont("Liberation Serif Italic", 12);
font = createFont("Arial", 12);
textFont(font);
// textMode(SCREEN);
// fill tree
// Params: ID, parentID, Content, branch open (all/multiple true), selected (only one true)
myTree[0] = new classNode ( 0, -1, "Wurzel: Fahrzeug", true, true );
myTree[1] = new classNode ( 1, 0, "Einrad", true, false );
myTree[2] = new classNode ( 2, 0, "Zweirad", true, false );
myTree[3] = new classNode ( 3, 0, "Dreirad", true, false );
myTree[4] = new classNode ( 4, 0, "Vierrad", true, false );
myTree[5] = new classNode ( 5, 2, "Fahrrad", false, false ); // not open
myTree[6] = new classNode ( 6, 2, "Motorrad", true, false );
myTree[7] = new classNode ( 7, 2, "Moped", true, false );
myTree[8] = new classNode ( 8, 4, "Auto", true, false );
myTree[9] = new classNode ( 9, 4, "Kutsche", true, false );
myTree[10] = new classNode ( 10, 3, "Kinderdreirad", true, false );
myTree[11] = new classNode ( 11, 1, "Einrad für Clowns", true, false );
myTree[12] = new classNode ( 12, 6, "MotoCross", true, false );
myTree[13] = new classNode ( 13, 6, "Straßen-Bike", true, false );
myTree[14] = new classNode ( 14, 5, "Crossrad", true, false );
myTree[15] = new classNode ( 15, 5, "Mountainbike", true, false );
myTree[16] = new classNode ( 16, 5, "Tourenrad", true, false );
myTree[17] = new classNode ( 17, 16, "Hollandrad", true, false );
// show tree as text (testing):
showContentLinear ();
println ("") ;
showContentAsTree ();
//
} // func
void draw () {
// MAIN
// delete screen
background (0);
// show as graphic
graphShowContentAsTree ();
// help
fill (color (222, 30, 10));
text ("usage: Crs Up Dn; - and + for branch", width-230, 22 );
} // func
// ============================================================
class classNode {
int ID; // ID of node
int parentID; // ID of parent
String strName=""; // Content
boolean boolIsOpen = true; // hide or show branch of the tree
boolean boolIsSelected = true; // hide or show branch of the tree
classNode ( int tempID, int tempParentID, String tempstrName, boolean tempboolIsOpen, boolean tempboolIsSelected ) {
// Constructor
ID = tempID;
parentID = tempParentID;
strName = tempstrName;
boolIsOpen = tempboolIsOpen;
boolIsSelected = tempboolIsSelected;
} // Constructor
String showContentAsString () {
// shows one Node as string
return(ID + " " + parentID + " " + strName);
} // func
} // class
This is a Tree with Data stored in it. Each node can have some children. Hiding and show selected branches with - and +. Cursor up and down moves the selection. F toggle view to 3D / 2D. When in 3D, use PeasyCam. Note that it has indent (depending on the depth of the node) in x direction (and also in z direction when in 3D).<br>
It's meant to store hierarchical data such as directory trees of hard drives. The data shown is only test data for fun showing vehicles with 1,2,3,4 wheels. ;-)<br>
I wanted to discuss how to maintain such a tree in a intelligent and elegant way. This isn't