home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dynamic HTML in Action
/
Dynamicke-HTML-v-akci-covermount.bin
/
XML
/
PARSER
/
XMLINST.EXE
/
viewer
/
XMLTreeView.java
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
Macintosh to JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Java Source
|
1997-10-31
|
49.2 KB
|
1,454 lines
//******************************************************************************
// XMLTreeView
//
//******************************************************************************
import java.awt.*;
import java.awt.Choice;
import java.util.Enumeration;
import com.ms.xml.parser.*;
import com.ms.xml.om.*;
import com.ms.xml.util.*;
import java.net.URL;
import Scroller;
class SpecialEnumeration implements Enumeration
{
public SpecialEnumeration(Element e)
{
this.en = new ElementEnumeration(e);
next();
}
public boolean hasMoreElements()
{
return (next != null);
}
public Object nextElement()
{
Element result = next;
next();
return result;
}
void next()
{
while (en.hasMoreElements())
{
next = (Element)en.nextElement();
if (next.getType() != Element.WHITESPACE)
return;
}
next = null;
}
Element next;
Enumeration en;
}
class XMLTreeView extends BufferedCanvas
{
public Image openFolder;
public Image closedFolder;
XMLTreeView() {
}
public void setDocument(Document d)
{
this.d = d;
viewText = false;
maxBranch = 0;
head = null;
getMaxBranch(this.d, 0); // This is needed so we can draw the proper tree lines later on.
setViewChoice( this.d.getRoot() );
focus = head;
focusY = 0;
if (focus != null)
focus.setAttribute( kFocus, "TRUE" );
newGraphics(); // Reset the graphic image to insure that everything is okay.
repaint();
}
public void showText(String text)
{
viewText = true;
reorient();
this.buffer = text;
invalidateBuffer();
repaint();
}
public void getMaxBranch( Element e, int branch )
{
if( e.numElements() > 0)
{
for( Enumeration en = new SpecialEnumeration(e); en.hasMoreElements(); )
{
Element child = ( Element )en.nextElement();
getMaxBranch( child, branch + 1 );
}
}
else
{
if( branch > maxBranch )
maxBranch = branch;
}
}
public String elementPos( Element e )
{
String elPos = new String("");
Element curr = e;
while( curr!=null && curr!=this.d )
{
Name currTagName = curr.getTagName();
if( currTagName != null )
elPos = currTagName.toString() + "\\" + elPos;
curr = curr.getParent();
}
return elPos;
}
public void setViewChoiceHelp( Element e )
{
if( e!=null && e!=this.d )
{
setViewChoiceHelp( e.getParent() );
choice.addItem( elementPos(e) );
}
}
public void setViewChoice( Element e )
{
sizeChange = true;
if( jdk11 ) // There is NO WAY to remove items from choice box before jdk11!
{
choice.removeAll();
setViewChoiceHelp( e );
int num = choice.countItems();
if( num == 0 )
return;
choice.select( num-1 );
}
head = e;
found = null;
findElement( this.d, head, 15, 0 );
if( found != null )
{
headX = foundX;
headY = foundY;
}
else
{
headX = 0;
headY = 0;
}
if( focus != null )
focus.removeAttribute( kFocus );
focus = head;
focus.setAttribute( kFocus, "TRUE" );
focusY = headY;
reorient();
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
invalidateBuffer();
}
//--------------------------------------------------------------------------
public void paintBuffer( Graphics g )
{
int treeHeightLines = 0;
maxWidth = 0;
g.setColor(Color.white);
Dimension dim = size();
Rectangle clip = g.getClipRect();
g.fillRect(clip.x, clip.y,
clip.width, clip.height);
g.setColor(Color.black);
if( !viewText )
{
treeLines = new int[maxBranch];
currLines = 0;
doneDraw = false;
stopDraw = false;
try {
if( head != null && head != this.d )
{
treeHeightLines = drawTree(g, head, 15, 0 );
}
else
{
treeHeightLines = drawTree(g, this.d, 15, 0);
}
} catch( Exception e ) {
treeHeightLines = 0;
g.setColor(Color.black);
g.drawString(e.toString(),10,15);
}
if (inside != null && pressed == null)
{
drawAttributes(g, inside, ax, ay);
}
}
else
{
int lines = viewDoc(g);
if (lines != treeHeightLines)
sizeChange = true;
treeHeightLines = lines;
}
if( sizeChange )
{
if( getDisplayHeightLines() != treeHeightLines + 1 )
{
displayHeight = YPOS(treeHeightLines + 1);
}
if( displayWidth != maxWidth )
{
displayWidth = maxWidth;
}
sizeChange = false;
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
}
//--------------------------------------------------------------------------
public int viewDoc(Graphics g)
{
int y = 1;
y = drawText( g, buffer, 10, y, getCanvasWidth(), false, buffer.length(), false, true );
return y;
}
//--------------------------------------------------------------------------
public void drawTreeLines( Graphics g, int y, boolean hasChildren, boolean hidden, boolean isHead )
{
if( isHead )
{
if( hasChildren )
{
g.drawLine(headX + 20 + 5, YPOS(y) + (fm.getMaxAscent()/2),
headX + 20 + 9, YPOS(y) + (fm.getMaxAscent()/2));
// Line coming out of folder
if(!hidden)
g.drawLine(headX + 20 + LEVELINDENT+INDENT, YPOS(y) + 12,
headX + 20 + LEVELINDENT+INDENT, YPOS(y) + (LINE_SIZE));
}
return;
}
for( int i = 0; i < currLines-1; i++ )
{
if( treeLines[i] >= 0 )
g.drawLine(treeLines[i],YPOS(y),
treeLines[i],YPOS(y)+(LINE_SIZE));
}
if( currLines != 0 )
{
boolean lastChild = false;
int x = treeLines[currLines-1];
if( x < 0 )
{
x *= -1;
lastChild = true;
}
if( !hasChildren )
{
if( !lastChild )
g.drawLine(x, YPOS(y),
x, YPOS(y) + (LINE_SIZE));
else
g.drawLine(x, YPOS(y),
x, YPOS(y) + (fm.getMaxAscent()/2));
g.drawLine(x, YPOS(y) + (fm.getMaxAscent()/2),
x + 15, YPOS(y) + (fm.getMaxAscent()/2));
}
else
{
// Need to avoid click box
g.drawLine(x, YPOS(y),
x, YPOS(y) + 1 );
if( !lastChild )
g.drawLine(x, YPOS(y) + 1 + RECT_SIZE,
x, YPOS(y) + (LINE_SIZE));
g.drawLine(x + 5, YPOS(y) + (fm.getMaxAscent()/2),
x + 9, YPOS(y) + (fm.getMaxAscent()/2));
// Line coming out of folder
if( !hidden )
g.drawLine(x + LEVELINDENT+INDENT, YPOS(y) + 12,
x + LEVELINDENT+INDENT, YPOS(y) + (LINE_SIZE));
}
}
int b = 10000;
}
//--------------------------------------------------------------------------
public void drawTextLines( Graphics g, int y, int height )
{
for( int i = 0; i < currLines-1; i++ )
{
if( treeLines[i] >= 0 )
g.drawLine(treeLines[i],YPOS(y),
treeLines[i],YPOS(y)+YPOS(height+1));
}
if( currLines != 0 )
{
boolean lastChild = false;
int x = treeLines[currLines-1];
if( x < 0 )
{
x *= -1;
lastChild = true;
}
if( !lastChild )
g.drawLine(x, YPOS(y),
x, YPOS(y) + YPOS(height+1));
else
g.drawLine(x, YPOS(y),
x, YPOS(y) + (fm.getMaxAscent()/2));
g.drawLine(x, YPOS(y) + (fm.getMaxAscent()/2),
x + 4, YPOS(y) + (fm.getMaxAscent()/2));
}
}
//--------------------------------------------------------------------------
public void drawElement( Graphics g, Element child, int x, int y )
{
int width = fm.stringWidth( child.getTagName().toString() );
String pressed = (String)child.getAttribute( kPressed );
String inside = (String)child.getAttribute( kInside );
String focus = (String)child.getAttribute( kFocus );
String hidden = (String)child.getAttribute( kHidden );
if (inside != null && inside.equals("TRUE"))
g.setColor(Color.blue); // Only set new color for INSIDE
boolean hasChildren = (child.numElements() > 0);
if (hasChildren) {
g.drawRect( x+1,YPOS(y)+1,RECT_SIZE,RECT_SIZE );
if (pressed != null && pressed == inside) {
g.drawRect(x+2,YPOS(y)+2,RECT_SIZE-2,RECT_SIZE-2); //Smaller rect inside larger
}
} else {
g.drawOval(x+20,YPOS(y),OVAL_SIZE,OVAL_SIZE);
}
if( focus != null )
{
if( hasFocus )
{
g.setColor( Color.blue );
g.fillRect( x+(OVAL_SIZE+FOLDER_SIZE+(INDENT*2))-SPACING, YPOS(y)-SPACING,
width+(SPACING*2), fm.getMaxAscent()+(SPACING*2) );
g.setColor( Color.white );
g.drawString(child.getTagName().toString(),
x+OVAL_SIZE+FOLDER_SIZE+(INDENT*2),YPOS(y)+fm.getMaxAscent());
g.setColor( Color.black );
}
else
{
g.drawRect( x+(OVAL_SIZE+FOLDER_SIZE+(INDENT*2))-SPACING, YPOS(y)-SPACING,
width+(SPACING*2), fm.getMaxAscent()+(SPACING*2) );
g.drawString(child.getTagName().toString(),
x+OVAL_SIZE+FOLDER_SIZE+(INDENT*2),YPOS(y)+fm.getMaxAscent());
}
}
else
g.drawString(child.getTagName().toString(),
x+OVAL_SIZE+FOLDER_SIZE+(INDENT*2),YPOS(y)+fm.getMaxAscent());
if (child.numAttributes() > 0 && child == this.inside && pressed == null) {
ax = x + 15 + 10;
ay = y + 2;
}
if( hasChildren ) {
if( hidden != null && hidden.equals("TRUE") ) {
g.drawLine(x+5,YPOS(y)+3,x+5,YPOS(y)+7);
g.drawLine(x+3,YPOS(y)+5,x+7,YPOS(y)+5);
g.drawImage(closedFolder, x+OVAL_SIZE+INDENT, YPOS(y)-SPACING, this);
} else {
g.drawLine(x+3,YPOS(y)+5,x+7,YPOS(y)+5);
g.drawImage(openFolder, x+OVAL_SIZE+INDENT, YPOS(y)-SPACING, this);
}
}
if (inside != null && inside.equals("TRUE"))
g.setColor(Color.black); // Set color back to black after INSIDE
drawTreeLines(g,y,hasChildren, (hidden != null && hidden.equals("TRUE")), (child == head));
}
//--------------------------------------------------------------------------
public int drawTree(Graphics g, Element e, int x, int y)
{
if( stopDraw || e == null )
return y;
if( isElement(e))
{
boolean eHasChildren = (e.numElements() > 0);
Rectangle onScreen = g.getClipRect();
int width = fm.stringWidth(e.getTagName().toString())+OVAL_SIZE+FOLDER_SIZE+(INDENT*2);
if( width + x > maxWidth )
maxWidth = width + x;
Rectangle elDraw = new Rectangle( x,YPOS(y), width, LINE_SIZE );
if( elDraw.intersects( onScreen ) ) { // We need to draw!
doneDraw = true;
drawElement( g, e, x, y );
}
else if( doneDraw && !sizeChange )
{
stopDraw = true;
return y;
}
if( eHasChildren && e.getAttribute(kHidden) == null )
{
// Turn lines on
treeLines[currLines] = x+20;
int tmpLines = currLines;
currLines++;
// Recurse down the tree
for( Enumeration en = new SpecialEnumeration(e); en.hasMoreElements(); )
{
Element child = (Element)en.nextElement();
if( !en.hasMoreElements() ) // Negative number implies this is last child.
treeLines[tmpLines] *= -1;
y = drawTree( g,child,x+LEVELINDENT+INDENT,y+1 );
if( stopDraw )
return y;
}
// Turn lines off completely
currLines--;
}
}
else if (e.getText() != null)
{
String sHeight = (String)e.getAttribute( kHeight );
int height;
if( sHeight == null || sizeChange)
{
// measure only
height = drawText(g, e.getText(),x+LEVELINDENT,
y,
getCanvasWidth() - x - 20,
true, 0, false, false) - y;
e.setAttribute(kHeight, Integer.toString(height));
}
else
{
height = Integer.valueOf(sHeight).intValue();
}
Rectangle onScreen = g.getClipRect();
// We add one to height because text lines reach down below the text.
Rectangle elDraw = new Rectangle( x,YPOS(y),
getCanvasWidth() - x - 20, YPOS(height+1) );
if( elDraw.intersects( onScreen ) )
{
Color c = Color.black;
switch (e.getType()) {
case Element.PI:
c = Color.magenta;
break;
case Element.ENTITY:
c = Color.green;
c.darker();
break;
case Element.CDATA:
c = Color.gray;
break;
case Element.PCDATA:
c = Color.black;
break;
case Element.COMMENT:
c = Color.red;
break;
}
g.setColor(c);
// draw the text
int y2 = drawText(g,
e.getText(),x+10,
y,
getCanvasWidth() - x - 20,
true, 0, false, true);
e.setAttribute(kHeight, Integer.toString(y2-y));
// Draw the tree lines
g.setColor(Color.black);
drawTextLines(g,y,(y2-y));
y = y2;
} else {
// measure only
int y2 = drawText(g, e.getText(),x+10,
y,
getCanvasWidth() - x - 20,
true, 0, false, false);
e.setAttribute(kHeight, Integer.toString(y2-y));
y = y2;
}
}
return y;
}
//--------------------------------------------------------------------------
public void drawAttributes(Graphics g, Element e, int x, int y)
{
int na = e.numAttributes();
String names = new String();
String values = new String();
int height = 0;
int col1 = 0;
int col2 = 0;
if (na > 0) {
boolean first = true;
for (Enumeration ena = e.getAttributes(); ena.hasMoreElements(); ) {
Attribute a = (Attribute)ena.nextElement();
if( a.getName() != null && a.getName().toString().length() > 0 && a.getName().toString().charAt(0) != '_' ) {
int w = fm.stringWidth(a.getName().toString());
if (w > col1) col1 = w;
String value = a.getValue().toString();
w = fm.stringWidth(value);
if (w > col2) col2 = w;
// The attribute height will never change, so we just need to find it once.
String sHeight = (String)e.getAttribute( kHeight );
int tHeight;
if( sHeight == null ) {
tHeight = (drawText(g,value,x,(y+height)+1,col2+3,true,0,true, false) - (y+height));
e.setAttribute(kHeight, Integer.toString(tHeight));
} else {
tHeight = Integer.valueOf(sHeight).intValue();
}
height += tHeight;
names += a.getName() + "\n";
values += value + "\n";
}
}
}
if( y+height+1 > getVertLines() + getCanvasHeightLines() )
{
y = y - height - 3; // Put the attribute above the Element rather then below
}
if (height > 0) {
g.setColor(Color.yellow);
int w = 3+col1+6+col2+3;
int h = 3+YPOS(height)+3;
g.fillRect(x,YPOS(y-1)+fm.getMaxAscent(),w,h);
g.setColor(Color.black);
g.drawRect(x,YPOS(y-1)+fm.getMaxAscent(),w,h);
int x2 = x+3+col1+3;
g.drawLine(x2,YPOS(y-1)+fm.getMaxAscent(),x2,YPOS(y-1)+fm.getMaxAscent()+h);
x += 3;
drawText(g, names, x, y, col1 + 3, true, 0, true, true);
x += col1+6;
drawText(g, values, x, y, col2 + 3, true, 0, true, true);
}
}
//--------------------------------------------------------------------------
public int drawText(Graphics g, String text, int x, int y, int max,
boolean skipWhiteSpace, int l, boolean attribute,
boolean draw) // whether to actually draw the text
{
if( text == null || text.length() == 0 )
return y;
if (max < 5) // make sure we have room to draw text.
return y;
int i = 0;
int len;
int w = 0;
if( l == 0 )
len = text.length();
else
len = l;
// skip leading white space.
while (i < len && skipWhiteSpace && isWhiteSpace(text.charAt(i)))
i++;
int j = i;
int k = i;
while (i < len) {
char ch = text.charAt(i);
int cw = fm.charWidth(ch);
w += cw;
if (w > max || ch == '\n') {
char prev = text.charAt(i-1);
if( ch == '\n' && prev == 0x0D )
j = i-1;
else if (attribute || k == j)
j = i;
if (draw) {
String sub = text.substring(k,j);
g.drawString(sub,x,YPOS(y)+fm.getMaxAscent());
}
y++;
// skip white space.
if( ch == '\n' && prev == 0x0D )
j = i;
if (ch == '\n')
j++;
while (skipWhiteSpace && j < len && isWhiteSpace(text.charAt(j)))
j++;
i = j;
k = j;
w = 0;
} else {
if (skipWhiteSpace && isWhiteSpace(ch)) {
j = i;
}
i++;
}
}
if (draw) {
String remaining = text.substring(k);
g.drawString(remaining,x,YPOS(y)+fm.getMaxAscent());
}
return y;
}
public boolean isWhiteSpace(char ch)
{
return Character.isSpace(ch) || ch == 13 || ch == 10;
}
public boolean isElement(Element e)
{
return e.getType() == Element.ELEMENT;
// || e.getType() == Element.ENTITY ;
}
//--------------------------------------------------------------------------
public int findElementAt( Element e, int x, int y, int x1, int y1 )
{
if ( isElement(e) )
{
boolean eHasChildren = (e.numElements() > 0);
Rectangle r = new Rectangle( x1,YPOS(y1),OVAL_SIZE,OVAL_SIZE );
int width = FOLDER_SIZE + INDENT + fm.stringWidth( e.getTagName().toString() );
Rectangle r2 = new Rectangle( x1+OVAL_SIZE+INDENT,YPOS(y1)-SPACING,
width, fm.getMaxAscent()+(SPACING*2));
if( r.inside(x,y) ) // inside the check box
{
boxClick = true;
found = e;
return y1;
}
if( r2.inside(x,y) ) // inside the tag
{
boxClick = false;
found = e;
return y1;
}
if( eHasChildren && e.getAttribute(kHidden) == null )
{
// Recurse down tree
for( Enumeration en = new SpecialEnumeration(e); en.hasMoreElements(); )
{
Element child = ( Element )en.nextElement();
int y2 = findElementAt( child,x,y,x1+LEVELINDENT+INDENT,y1+1 );
if ( found != null )
return y2;
y1 = y2;
}
}
}
else
{
String s = (String)e.getAttribute(kHeight);
if (s != null)
y1 += Integer.valueOf(s).intValue();
}
return y1;
}
//--------------------------------------------------------------------------
public int findElementAtLine( Element e, int line, int x1, int y1 )
{
if( line == y1 )
{
if ( isElement(e) )
{
found = e;
return y1;
}
else
{
found = prevVisibleElement( e );
Element temp = found;
found = null;
return findElement(head, temp, 15 + headX, headY);
}
}
if( isElement(e) )
{
if( e.numElements() > 0 && e.getAttribute(kHidden) == null )
{
for( Enumeration en = new SpecialEnumeration(e); en.hasMoreElements(); )
{
Element child = ( Element )en.nextElement();
int y2 = findElementAtLine( child,line,x1+LEVELINDENT+INDENT,y1+1 );
if ( found != null )
return y2;
y1 = y2;
}
}
}
else
{
String s = (String)e.getAttribute(kHeight);
if (s != null)
y1 += Integer.valueOf(s).intValue();
}
return y1;
}
//--------------------------------------------------------------------------
public int findElement( Element e, Element find, int x1, int y1 )
{
if ( isElement(e) )
{
if( e == find )
{
found = e;
foundX = x1;
foundY = y1;
return y1;
}
if( e.numElements() > 0 && e.getAttribute(kHidden) == null )
{
// Recurse down the tree
for( Enumeration en = new SpecialEnumeration(e); en.hasMoreElements(); )
{
Element child = ( Element )en.nextElement();
int y2 = findElement( child,find,
x1+LEVELINDENT+INDENT,y1+1 );
if ( found != null )
return y2;
y1 = y2;
}
}
}
else
{
String s = (String)e.getAttribute(kHeight);
if (s != null)
y1 += Integer.valueOf(s).intValue();
}
return y1;
}
//--------------------------------------------------------------------------
public boolean mouseMove(Event evt, int x, int y)
{
if( viewText )
return false;
if( x == prevX && y == prevY )
return false;
prevX = x;
prevY = y;
found = null;
x += (getHorz() - (BUFFER*2));
y += (getVert() - (BUFFER*2));
findElementAt( head,x,y,15 + headX, headY );
if( found != inside && inside != null )
{
inside.removeAttribute( kInside );
inside = null;
invalidateBuffer();
repaint();
}
if( found != null )
{
found.setAttribute( kInside,"TRUE" );
inside = found;
invalidateBuffer();
repaint();
}
return true;
}
public boolean mouseDrag( Event evt, int x, int y )
{
if( viewText )
return false;
found = null;
x += (getHorz() - (BUFFER*2));
y += (getVert() - (BUFFER*2));
findElementAt( head,x,y,15 + headX, headY );
if( found != inside && inside != null )
{
// inside should be redrawNew
inside.removeAttribute(kInside);
inside = null;
invalidateBuffer();
repaint();
}
if( found != null && found == pressed )
{
found.setAttribute( kInside,"TRUE" );
inside = found;
invalidateBuffer();
repaint();
}
return true;
}
public boolean mouseDown(Event evt, int x, int y)
{
if( viewText )
return false;
found = null;
boxClick = false;
x += (getHorz() - (BUFFER*2));
y += (getVert() - (BUFFER*2));
int foundY;
foundY = findElementAt( head,x,y,15 + headX, headY );
if( found != null )
{
hasFocus = true;
if( focus != null ) // We need to remove the previous focus
{
focus.removeAttribute( kFocus );
focus = null;
}
if (inside != null)
{
inside.removeAttribute(kInside);
inside = null;
}
if( evt.clickCount > 1 )
{
setViewChoice( found );
repaint();
return true;
}
if( boxClick )
{
found.setAttribute( kPressed,"TRUE" );
sizeChange = true;
pressed = found;
}
found.setAttribute( kFocus,"TRUE" );
inside = found;
found.setAttribute( kInside,"TRUE" );
focus = found;
focusY = foundY;
invalidateBuffer();
repaint();
}
else if( hasFocus && focus != null )
{
hasFocus = false;
invalidateBuffer();
repaint();
}
return true;
}
public boolean mouseUp(Event evt, int x, int y)
{
if( viewText )
return false;
found = null;
boxClick = false;
x += (getHorz() - (BUFFER*2));
y += (getVert() - (BUFFER*2));
findElementAt( head,x,y,15 + headX, headY );
if( found == pressed && boxClick == true )
{
if( pressed.getAttribute(kHidden) != null )
{
pressed.removeAttribute( kHidden );
}
else
{
pressed.setAttribute( kHidden, "TRUE" );
}
sizeChange = true;
invalidateBuffer();
repaint();
}
if( pressed != null )
{
pressed.removeAttribute( kPressed );
pressed.removeAttribute( kInside );
pressed = null;
inside = null;
invalidateBuffer();
repaint();
}
return true;
}
//--------------------------------------------------------------------------
public Element lastVisibleChild( Element parent )
{
boolean hasChildren = ( parent.numElements() > 0 );
if( !hasChildren || parent.getAttribute( kHidden ) != null )
return parent;
Enumeration en = new SpecialEnumeration(parent);
Element child;
Element lastElement = null;
while( en.hasMoreElements() )
{
child = ( Element )en.nextElement();
if( isElement(child))
lastElement = child;
}
if( lastElement == null )
return parent;
else
return lastVisibleChild( lastElement );
}
public Element prevVisibleElement( Element current )
{
Element parent = current.getParent();
if( parent == null )
return null;
Element curr = null;
Element lastElement = null;
Enumeration en = new SpecialEnumeration(parent);
while( en.hasMoreElements() )
{
curr = ( Element )en.nextElement();
if( curr == current )
{
if( lastElement == null )
return parent;
else
{
return lastVisibleChild( lastElement );
}
}
if( isElement(curr) )
lastElement = curr;
}
// Something went wrong...
return null;
}
public Element nextVisibleElement( Element current, Element original )
{
boolean seenOriginal = ( original == current );
boolean hasChildren = ( current.numElements() > 0 );
String hidden = (String)current.getAttribute( kHidden );
if( hasChildren && ( hidden == null ) )
{
Enumeration en = new SpecialEnumeration(current);
while( en.hasMoreElements() )
{
Element child = ( Element )en.nextElement();
if( seenOriginal )
{
if( isElement(child) )
{
return child;
}
}
if( child == original )
seenOriginal = true;
}
}
Element parent = current.getParent();
if( parent == null )
return null;
else
return nextVisibleElement( parent, current );
}
//--------------------------------------------------------------------------
public boolean keyDown( Event evt, int key )
{
if( viewText )
return false;
switch( key )
{
case Event.UP:
{
if( focus == head )
return true;
Element newFocus = prevVisibleElement( focus );
if( newFocus != null && newFocus != this.d )
{
focus.removeAttribute( kFocus );
focus = newFocus;
// We need to reset position
found = null;
focusY = findElement( head, focus, 15 + headX, headY );
if( focusY < getVertLines() )
{
setTopLine( focusY );
}
else if( focusY >= getVertLines() + getCanvasHeightLines() )
{
setBottomLine( focusY );
}
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
invalidateBuffer();
repaint();
}
}
return true;
case Event.PGUP:
{
if( focus == head )
return true;
focus.removeAttribute( kFocus );
found = null;
int tempY = findElementAtLine( head, getVertLines(), 15 + headX, headY );
if( focus == found )
{
found = null;
tempY = findElementAtLine( head, getVertLines() - getCanvasHeightLines(), 15 + headX, headY );
}
if( found != null && tempY > headY )
{
if( tempY >= getVertLines() + getCanvasHeightLines() )
{
setBottomLine( tempY );
}
else if( tempY < getVertLines() )
{
setTopLine( tempY );
}
focus = found;
focusY = tempY;
}
else // go to top of the list
{
focus = head; // This will return first vis.
focusY = headY;
setTopLine( focusY );
}
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
invalidateBuffer();
repaint();
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
return true;
case Event.DOWN:
{
if( focus == lastVisibleChild( head ) )
return true;
Element newFocus = nextVisibleElement( focus, focus );
if( newFocus != null )
{
focus.removeAttribute( kFocus );
focus = newFocus;
// We need to reset position
found = null;
focusY = findElement( head, focus, 15 + headX, headY );
if( focusY >= getVertLines() + getCanvasHeightLines() )
{
setBottomLine( focusY );
}
else if( focusY < getVertLines() )
{
setTopLine( focusY );
}
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
invalidateBuffer();
repaint();
}
}
return true;
case Event.PGDN:
{
Element last = lastVisibleChild(head);
if( focus == last )
return true;
found = null;
int lastY = findElement( head, last, 15 + headX, headY );
focus.removeAttribute( kFocus );
found = null;
int tmpY = findElementAtLine( head, getVertLines()+getCanvasHeightLines()-1, 15 + headX, headY );
if( focus == found )
{
found = null;
tmpY = findElementAtLine( head, getVertLines()+2*getCanvasHeightLines(), 15 + headX, headY );
}
if( found != null && tmpY < lastY )
{
if( tmpY >= getVertLines() + getCanvasHeightLines() )
{
setBottomLine( tmpY );
}
else if( tmpY < getVertLines() )
{
setTopLine( tmpY );
}
focus = found;
focusY = tmpY;
}
else // Just go to bottom of visible list
{
focus = last;
focusY = lastY;
setBottomLine( focusY );
}
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
invalidateBuffer();
repaint();
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
return true;
case '\n':
setViewChoice( focus );
repaint();
return true;
case Event.RIGHT:
{
boolean hasChildren = ( focus.numElements() > 0 );
if( hasChildren )
{
if (focus.getAttribute( kHidden ) != null)
{
keyDown( null, ' ' );
}
keyDown( null, Event.DOWN );
}
}
return true;
case ' ':
{
boolean hasChildren = ( focus.numElements() > 0 );
if(hasChildren) {
if (focus.getAttribute( kHidden ) == null )
{
focus.setAttribute( kHidden, "TRUE" );
} else {
focus.removeAttribute( kHidden );
}
sizeChange = true;
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
invalidateBuffer();
repaint();
}
}
return true;
case Event.LEFT:
{
// Otherwise do the standard left movement
Element parent = focus.getParent();
if( parent == null )
return true;
if( focus == head ) {
parent = head.getParent();
if( parent == null || parent == this.d )
return true;
setViewChoice( parent );
repaint();
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
hasFocus = true;
return true;
}
focus.removeAttribute( kFocus );
focus = parent;
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to reset position
found = null;
focusY = findElement( head, focus, 15 + headX, headY );
if( focusY < getVertLines() )
{
setTopLine( focusY );
sizeChange = true;
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
else if( focusY >= getVertLines() + getCanvasHeightLines() )
{
setBottomLine( focusY );
sizeChange = true;
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
invalidateBuffer();
repaint();
}
return true;
case Event.HOME:
{
// Give head of list focus.
if( focus == head )
return true;
focus.removeAttribute( kFocus );
focus = head;
focusY = headY;
setTopLine( focusY );
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
invalidateBuffer();
repaint();
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
return true;
case Event.END:
{
// Give last item in list focus
Element last = lastVisibleChild(head);
if( focus == last )
return true;
found = null;
int lastY = findElement( head, last, 15 + headX, headY );
focus.removeAttribute( kFocus );
focus = last;
focusY = lastY;
setBottomLine( focusY );
focus.setAttribute( kFocus, "TRUE" );
hasFocus = true;
// We need to set a new inside
if( inside != null )
inside.removeAttribute( kInside );
inside = focus;
inside.setAttribute( kInside, "TRUE" );
invalidateBuffer();
repaint();
postEvent(new Event(null, DISPLAY_SIZE_CHANGE, null));
}
return true;
}
return false;
}
public boolean action(Event evt, Object what)
{
if( evt.id == Event.ACTION_EVENT )
{
String s = (String)evt.arg;
if (evt.target == choice )
{
choice.select( s );
int pos = choice.getSelectedIndex();
Element newHead = head;
for( int i = choice.countItems(); i > pos+1; i-- )
{
if( newHead != null ) // This shouldn't ever be the case... but to be safe.
newHead = newHead.getParent();
}
if( newHead != head && newHead != null )
{
setViewChoice( newHead );
repaint();
}
}
}
return false;
}
public boolean handleEvent( Event evt )
{
switch( evt.id )
{
case Event.LOST_FOCUS:
{
if (inside != null)
{
inside.removeAttribute( kInside );
inside = null;
}
hasFocus = false;
invalidateBuffer();
repaint();
}
break;
case Event.GOT_FOCUS:
{
hasFocus = true;
invalidateBuffer();
repaint();
}
break;
}
return super.handleEvent( evt );
}
Document d = new Document();
Element head = null; // the element that heads the view
int headX, headY;
Element pressed; // the element that the mouse is currently pressing
Element inside; // the element that the mouse is over
Element focus; // the element with focus
int focusY;
boolean hasFocus = false; // This indicates if the focus has focus, not the window.
Element found;
int foundX, foundY;
int prevX = 0;
int prevY = 0;
int maxWidth = 0;
boolean boxClick; // was the click on the box or on the tag
int ax = 0; // position of attributes for "inside" element.
int ay = 0;
// Variables for keeping track of the tree branch drawing
int maxBranch;
int[] treeLines;
int currLines;
boolean viewText;
String buffer;
Choice choice;
boolean sizeChange = true;
boolean doneDraw = false;
boolean stopDraw = false;
Name kInside = Name.create("_INSIDE");
Name kPressed = Name.create("_PRESSED");
Name kHidden = Name.create("_HIDDEN");
Name kFocus = Name.create("_FOCUS");
Name kHeight = Name.create("_HEIGHT");
}