home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Late Night VRML 2.0 with Java CD-ROM
/
code.zip
/
Ch12
/
ui
/
tree
/
treeCanvas.java
< prev
next >
Wrap
Text File
|
1997-01-02
|
7KB
|
274 lines
package ui.tree;
import java.awt.*;
import ui.tree.*;
public class treeCanvas extends Canvas implements TreeToolObserver
{
protected int width = 20;
protected int height = 20;
protected int xPos = 0;
protected int yPos = 0;
protected TreeNode root = null;
protected ScrollerInterface scroller = null;
protected TreeTool tool = null;;
public TreeNode selected = null;
public Dimension psize = null; // preferred size
public Dimension tsize = null; // total (tree) size
// draw to offscreen graphics from example GraphLayout (SUN)
protected Image offscreen = null;
private Dimension offscreensize = null;
protected Graphics offgraphics = null;
// some layout constants
public int horizontal_offset = 30;
public int vertical_offset = 20;
public Color line_color = Color.black;
public Color background_color = Color.white;
public treeCanvas(TreeTool t)
{
// constructor for root node
offscreensize = new Dimension(0,0); // intitial size is zero
tsize = new Dimension(-1, -1);
tool = t!=null?t:tool;
startObserving();
}
public int getImageHeight()
{
return(tsize.height);
}
public int getImageWidth()
{
return(tsize.width);
}
public Dimension preferredSize() {
// System.out.println("TreeViewPanel::preferredSize() is "+psize);
return tsize;
}
public void startObserving() {
recomputeTree();
tool.addObserver(this);
}
public void stopObserving() {
tool.removeObserver(this);
}
public void nodeSelected(TreeNode node) {
selected = node;
//System.out.println("Node selected = " + selected.toString());
repaint();
}
public void nodeUnSelected(TreeNode node) {
selected = null;
repaint();
}
public void nodeOpened(TreeNode node) {
//System.out.println("Node opened");
fullUpdate();
}
public void nodeClosed(TreeNode node) {
//System.out.println("Node closed");
fullUpdate();
}
public void nodeAdded(TreeNode where,TreeNode node) {
fullUpdate();
}
public void nodeRemoved(TreeNode node) {
fullUpdate();
}
public void fullUpdate() {
// System.out.println("TreeViewPanel::fullUpdate()");
recomputeTree();
repaint();
}
// Used to remove subtrees from the tree structure
public void removeNode(TreeNode n)
{
tool.tree.removeNode(n);
fullUpdate();
}
public Dimension computeTree(TreeNode node,int x,int y)
{
// System.out.println("TreeViewPanel::computeTree("+node+","+x+","+y+")");
Dimension child_extent = null;
node.x = x;
node.y = y;
int hei = node.hei;
int wid = node.wid;
int xc = x+horizontal_offset;
int yc = y+hei+vertical_offset;
int num = 0;
if (node.isOpen())
num = node.numberChilds();
for (int i=0;i<num;i++)
{
TreeNode child = node.getChild(i);
child_extent = computeTree(child,xc,yc);
if (child_extent.width+horizontal_offset>wid)
wid = child_extent.width+horizontal_offset;
yc += child_extent.height+vertical_offset;
}
hei = yc - y - vertical_offset;
return new Dimension(wid,hei);
}
public void recomputeTree() {
//System.out.println("TreeViewPanel::recomputeTree()");
int x = horizontal_offset;
int y = vertical_offset;
int width;
int height;
Dimension extent = computeTree(tool.tree.root,x,y);
width = x+extent.width+horizontal_offset;
height= y+extent.height+vertical_offset;
//System.out.println("offscreensize.width = " + offscreensize.width + " offscreensize.height = " + offscreensize.height);
tsize.width = width;
tsize.height = height;
//System.out.println("Tsize.width = " + tsize.width + " tsize.height = " + tsize.height);
//System.out.println("offscreensize.width = " + offscreensize.width + " offscreensize.height = " + offscreensize.height);
//System.out.println(" ");
//System.out.println("tree computed, extent is " + tsize.width + " " + tsize.height);
}
public void drawTree(Graphics g,TreeNode node) {
// System.out.println("TreeViewPanel::drawTree("+node+")");
node.draw(g);
int lx = node.x+(horizontal_offset/2);
int ly = node.y+node.hei;
int yp = -1;
int num = 0;
if (node.isOpen())
num = node.numberChilds();
for (int i=0;i<num;i++)
{
TreeNode child = node.getChild(i);
// draw horizontal line
yp = child.y+(child.hei/2);
g.setColor(line_color);
g.drawLine(lx,yp,child.x,yp);
// draw sub-tree
drawTree(g,child);
}
if (yp>0) { // draw vertical line
g.setColor(line_color);
g.drawLine(lx,ly,lx,yp);
}
}
public void update(Graphics g) {
// System.out.println("TreeViewPanel::update()");
// force redraw :
offscreen = null;
paint(g);
}
public void paint(Graphics g)
{
Dimension d = size();
if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height))
{
offscreen = createImage(d.width,d.height);
offscreensize = tsize;
offgraphics = offscreen.getGraphics();
offgraphics.setFont(getFont());
offgraphics.setColor(background_color);
offgraphics.fillRect(0, 0, d.width, d.height);
}
offgraphics.translate(-1 * ((scrollPanel)getParent()).imgX,-1 * ((scrollPanel)getParent()).imgY);
drawTree(offgraphics,tool.tree.root);
g.drawImage( offscreen,0,0,null ) ;
}
public Dimension getImageSize()
{
return(tsize);
}
public TreeNode findNode(TreeNode start,int x,int y)
{
// since we know all the node's positions , this could be
// done in a much faster way, but for now : simply brute force !
// System.out.println("TreeViewPanel::findNode("+start+")");
if (start.inside(x,y))
return start;
else
{
if (start.isLeaf())
return null;
else
{
int num = start.numberChilds();
int i=0;
TreeNode found = null;
while ((found==null) && (i<num))
{
TreeNode ch = start.getChild(i);
if (ch.isOpen()) // dont check closed subtrees !
found = findNode(ch,x,y);
else
{
if (ch.inside(x,y))
found = ch;
else found = null;
}
i++;
}
return found;
}
}
}
public boolean mouseDown(Event evt,int x,int y)
{
// System.out.println("TreeViewPanel::mouseDown("+x+","+y+")");
//if (scroller!=null)
//{
// int h_val = scroller.getHorizontalScrollerVal();
// int v_val = scroller.getVerticalScrollerVal();
// x += h_val;
// y += v_val;
//}
TreeNode found = findNode(tool.tree.root,x,y);
if (found==null)
{ // no node found -> unselect all
if (selected!=null)
tool.unSelectNode(selected);
return true;
}
if (found==selected)
{ // double click -> toggle open/close
if (found.isOpen())
tool.closeNode(found);
else
tool.openNode(found);
}
else
{ // new selection -> unselect old and select new one
if (selected!=null)
tool.unSelectNode(selected);
tool.selectNode(found);
}
return true;
}
}