package javaforce.webui;
/** Tree
*
* @author pquiring
*/
import javaforce.webui.event.*;
public class Tree extends ScrollPanel implements Click {
public Tree() {
removeClass("column");
addClass("tree");
model = new TreeModel(new TreeNode());
}
public Tree(TreeModel model) {
removeClass("column");
addClass("tree");
this.model = model;
}
private TreeModel model;
public void init() {
rebuild();
super.init();
}
public String html() {
StringBuffer sb = new StringBuffer();
sb.append("<div" + getAttrs() + "'>");
sb.append(innerhtml());
sb.append("</div>");
return sb.toString();
}
public String innerhtml() {
StringBuffer sb = new StringBuffer();
int cnt = count();
for(int a=0;a<cnt;a++) {
sb.append(get(a).html());
}
return sb.toString();
}
public void setRootNode(TreeNode newRoot) {
model.setRoot(newRoot);
rebuild();
sendEvent("sethtml", new String[] {"html=" + innerhtml()});
}
public TreeNode getRootNode() {
return model.getRoot();
}
private void addNode(TreeNode node, int offset) {
Block row = new Block();
row.setClass("treerow");
row.display = "flex";
add(row);
row.setProperty("node", node);
row.addClickListener(this);
for(int a=0;a<offset;a++) {
Block b = new Block();
b.setClass("treeindex");
row.add(b);
}
if (node.hasChildren() && !node.leaf) {
Block b = new Block();
if (node.opened) {
b.setClass("treeopened");
row.add(b);
} else {
b.setClass("treeclosed");
row.add(b);
}
b.addEvent("onclick", "onClick(event," + row.id + ");");
b.addClickListener(this);
row.setProperty("open_close", b);
} else {
Block b = new Block();
b.setClass("treeleaf");
row.add(b);
}
Label l = new Label(node.toString());
l.setClass("treelabel");
l.addEvent("onclick", "onClick(event," + row.id + ");");
l.addClickListener(this);
row.add(l);
int cnt = node.getChildCount();
offset++;
for(int a=0;a<cnt;a++) {
addNode(node.getChildAt(a), offset);
}
}
private void rebuild() {
removeAll();
addNode(model.getRoot(), 0);
}
private TreeEventClick handler;
public void addEventHandler(TreeEventClick handler) {
this.handler = handler;
}
private Block getRow(TreeNode node) {
int cnt = count();
for(int a=0;a<cnt;a++) {
Block row = (Block)get(a);
if (row.getProperty("node") == node) {
return row;
}
}
return null;
}
private void setNodeVisible(TreeNode node, boolean state) {
Block row = getRow(node);
row.setVisible(state);
int cnt = node.getChildCount();
for(int a=0;a<cnt;a++) {
setNodeVisible(node.getChildAt(a), state);
}
}
private void setNodeChildrenVisible(TreeNode node, boolean state) {
int cnt = node.getChildCount();
for(int a=0;a<cnt;a++) {
setNodeVisible(node.getChildAt(a), state);
}
Block row = (Block)getRow(node);
Block oc = (Block)row.getProperty("open_close");
oc.setClass(state ? "treeopened" : "treeclosed");
}
public void onClick(MouseEvent e, Component c) {
TreeNode node = (TreeNode)c.getProperty("node");
if (node == null) return;
if (!node.hasChildren() || node.leaf) {
//trigger click event
if (handler != null) handler.nodeClick(node);
} else {
//open or close node
node.opened = !node.opened;
setNodeChildrenVisible(node, node.opened);
}
}
}