import java.awt.*; import java.util.*; import java.io.*; import java.net.*; import java.applet.*; import java.awt.event.*; /** * slidescroll_canvas represents the drawing surface of the applet, a scrolling tree is drawn on this canvas. * While the user will see a tree similar to the windows explorer tree, internally in this program * the tree is represented as objects in the navItemVector. Whenever the tree expands, an item object is * added to the navItemVector, when the tree contracts, item objects are removed from the navItemVector. * Item objects represent lables or nodes in the tree, some labels will wrap to the next line in the tree * using word wrap, when this happenes, the item object is duplicated int the navItemVector for as many lines * as the label wraps. * */ class slidescroll_canvas extends Canvas implements MouseListener, MouseMotionListener { slidescroll ns; int nc_width; int nc_height; int nc_x; int nc_y; String temp; Image closeItem; Image openItem; MediaTracker mt; slidescroll_item item; Vector linkVector; Vector indexVector; FontMetrics fm; String target = ""; String first = ""; Color backgroundColor; Color highliteColor; Color textColor1; Color textColor2; Color arrowColor; int z; String treeIndex; String treeLink; String hostPath; int fontStyle; Image offscreen = null; Graphics offscreeng; Vector navItemVector; Enumeration enum; int lineSpace = 0; int startLines = 0; int lastLineIndex = -1; int lineSelect = -1; int lineDown = 0; boolean mouseexit = true; int fontSize = 0; int tempInt; String fontType; Font font; int mousex; int mousey; boolean mouseDown = false; int pauseValue = 15; boolean startup = true; String openPath = ""; int linkSavIndex = -1; slidescroll_item linkSavItem = null; int menuSavIndex = -1; slidescroll_item menuSavItem = null; Color arrowShadeColor; Color bulletColor; Color bulletShadeColor; Color dotColor; String nameValueParameters = ""; String childLink = null; String childTarget = null; int dotSpace = 2; int width = -1; Image scrollBar; Graphics scrollBarg; int scrollBarWidth = 10; int sbx = scrollBarWidth-5; int sby = 0; int mousedx; int mousedy; int scrollx = sbx-1; Color scrollBarColor; Image bullet; int mouseOverStyleEffect; boolean mouseOverBulletEffect; boolean mouseOverArrowEffect; boolean highliteEffect; String source; //web, plus, xtra int y = 0; MouseEvent me = null; slidescroll_canvas(slidescroll ns, int nc_x, int nc_y, int nc_width, int nc_height) { init(ns, nc_x, nc_y, nc_width, nc_height); } public void init(slidescroll ns, int nc_x, int nc_y, int nc_width, int nc_height) { linkVector = new Vector(50); indexVector = new Vector(50); navItemVector = new Vector(50); this.ns = ns; this.nc_x = nc_x; this.nc_y = nc_y; this.nc_width = nc_width; this.nc_height = nc_height; setBounds(nc_x, nc_y, nc_width, nc_height); width = nc_width-scrollBarWidth; hostPath = ns.getCodeBase().toString(); source = ns.getParameter("source"); if(source == null) source = "web"; pauseValue = ns.getNumber("scrollDelay"); if(pauseValue < 0) pauseValue = 1; target = ns.getParameter("target"); if(target == null) target = "_top"; fontSize = ns.getNumber("fontSize"); if(fontSize < 0) fontSize = 12; lineSpace = ns.getNumber("lineSpace"); if(lineSpace < 0) lineSpace = 12; tempInt = ns.getFont("fontType"); if(tempInt < 0) fontType = ns.fontArray2[0]; else fontType = ns.fontArray2[tempInt]; treeIndex = ns.getParameter("treeIndex"); if(treeIndex == null) treeIndex = "treeIndex.txt"; treeLink = ns.getParameter("treeLink"); if(treeLink == null) treeLink = "treeLink.txt"; backgroundColor = ns.getColor("backgroundColor"); if(backgroundColor == null) backgroundColor = new Color(0,0,153); setBackground(backgroundColor); highliteColor = ns.getColor("highliteColor"); if(highliteColor == null) highliteColor = new Color(255,102,0); textColor1 = ns.getColor("textColor1"); if(textColor1 == null) textColor1 = Color.cyan; textColor2 = ns.getColor("textColor2"); if(textColor2 == null) textColor2 = Color.white; arrowColor = ns.getColor("arrowColor"); if(arrowColor == null) arrowColor = Color.white; arrowShadeColor = ns.getColor("arrowShadeColor"); if(arrowShadeColor == null) arrowShadeColor = Color.lightGray; bulletColor = ns.getColor("bulletColor"); if(bulletColor == null) bulletColor = Color.white; bulletShadeColor = ns.getColor("bulletShadeColor"); if(bulletShadeColor == null) bulletShadeColor = Color.gray; scrollBarColor = ns.getColor("scrollBarColor"); if(scrollBarColor == null) scrollBarColor = Color.gray; dotColor = ns.getColor("dotColor"); if(dotColor == null) dotColor = Color.white; dotSpace = ns.getNumber("dotSpace"); if(dotSpace < 0) dotSpace = 2; dotSpace++; openPath = ns.getParameter("Path"); z = ns.getStyle("fontStyle"); if(z < 0) fontStyle = Font.BOLD; else fontStyle = ns.StyleMap[z]; mouseOverBulletEffect = ns.setBoolean("mouseOverBulletEffect"); mouseOverArrowEffect = ns.setBoolean("mouseOverArrowEffect"); highliteEffect = ns.setBoolean("highliteEffect"); z = ns.getStyle("mouseOverStyleEffect"); if(z < 0) mouseOverStyleEffect = Font.BOLD; else mouseOverStyleEffect = ns.StyleMap[z]; addMouseListener(this); addMouseMotionListener(this); } public void update(Graphics g) { paint(g); } public void setUpTree() { getParmLink(); //read the link parameters into a Vector getParmIndex(); //read the index parameters into a Vector createRootChildren(); //create the children of the root nodes //get the height of the offscreen image int height = (navItemVector.size()+1)*lineSpace; if(height < nc_height) height = nc_height; //create the offscreen image and fill in the background color offscreen = createImage(width, height); offscreeng = offscreen.getGraphics(); offscreeng.setColor(getBackground()); offscreeng.fillRect(0,0, width, height); //create the scrollbar image scrollBar = createImage(scrollBarWidth, nc_height); scrollBarg = scrollBar.getGraphics(); drawScrollBar(); //draw the scrollbar setUpOffscreen(); //draw the offscreen image int pause_save = pauseValue; pauseValue = 0; openTree(); pauseValue = pause_save; } /** * This method creates an image object */ void getPicImage(Image i, String s) { mt = new MediaTracker(this); i = ns.getImage(ns.getCodeBase(), s); mt.addImage(i, 0); try { mt.checkID(0, true); mt.waitForID(0); } catch(InterruptedException e2){} } /** * This method creates the children of the root nodes. */ void createRootChildren() { // String parm = ns.getParameter("index1"); StringTokenizer t = new StringTokenizer(parm, ";"); parm = t.nextToken(); //bump past "root" font = new Font(fontType, fontStyle, fontSize); fm = getFontMetrics(font); while(t.hasMoreTokens()) { //bump past spaces parm = t.nextToken(); if(!parm.trim().equals("")) break; } //create item objects and children while(true) { boolean last = true; if(t.hasMoreTokens()) last = false; getLink(parm); item = new slidescroll_item(this, parm, true, null, true, childLink, childTarget, 15, fontType, fontStyle, fontSize, last, bullet, arrowColor, arrowShadeColor,bulletColor, bulletShadeColor, highliteColor); item.addVector(navItemVector); if(!t.hasMoreTokens()) break; parm = t.nextToken(); } } public void paint(Graphics g) { g.drawImage(offscreen, 0, y, this); //draw the tree g.drawImage(scrollBar, width, 0, this); //draw the scrollbar } /** * This method creates the scroll bar when the height of the offscreen image is greater than the height of the applet. */ void drawScrollBar() { int xpos = scrollx; int ypos = 5; scrollBarg.setColor(getBackground()); scrollBarg.fillRect(0, 0, scrollBarWidth, nc_height); int height = navItemVector.size()*lineSpace; if(sby <= 0 && height < nc_height ) { sby = 0; return; } //set the scrollbar color scrollBarg.setColor(scrollBarColor); //draw 2 lines scrollBarg.drawLine(xpos+1, ypos, xpos+1, nc_height-5); scrollBarg.drawLine(xpos, ypos, xpos, nc_height-5); //draw the "elevator" the user will drag Polygon p = new Polygon(); p.addPoint(sbx-0, sby); p.addPoint(sbx-5, sby+5); p.addPoint(sbx-0, sby+10); p.addPoint(sbx+5, sby+5); scrollBarg.fillPolygon(p); //draw a line in the middle of the "elevator" scrollBarg.setColor(getBackground()); scrollBarg.drawLine(sbx-6, sby+5, sbx+4, sby+5); } /** * This method is called when the mouse is dragged. If the mouse is dragged on the scrollbar, * scroll the vertically. */ public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); //is the mouse over the scrollbar? if(x >= width) { //calculate how far the mouse was dragged int diffy = y - mousedy; // for example -> this ypos 7 - last ypos 6 = mouse dragged 1 pixel //keep the "elevator" in sync with the mouse sby = sby+diffy; //for example -> move scrollbar "elevator" 1 pixel down //don't scroll the "elevator" off the screen if(sby < 0) sby = 0; if(sby > nc_height-10) sby = nc_height-10; //get the height of the tree int height = (navItemVector.size()+1)*lineSpace; //calculate the percentage the scrollbar is down relative to the height of the applet float vp = (float)sby/(float)nc_height; //calculate the y pos by multipling the percentage times the height of the tree vp = (float)height * vp; //use the y pos when calling repaint this.y = -(int)vp; //-y is the number of pixels the tree is above the applet view drawScrollBar(); repaint(); if(height < nc_height) height = nc_height; //clear drawing surface under the tree. Removes that unsightly "trail". if(height+this.y < nc_height) { Graphics g = getGraphics(); g.setColor(getBackground()); g.fillRect(0, height+this.y, nc_width-scrollBarWidth, -this.y); } } mousedx = x; mousedy = y; } /** * This method will recalculate the ypos of the scrollbars "elevator" when the tree is expanded or contracted. */ void recalcScrollBar() { //get the height of the tree int height = (navItemVector.size()+1)*lineSpace; //calculate the percentage the tree is scrolled up float vp = (float)-y/(float)height; //apply percentage to height of canvas giving new sby sby = (int)(nc_height * vp); } /** * Create the offscreen image that will display. Use the navItemVector to represent the displayed tree, * and call the drawLines method in each slidescroll_item object to draw itself to the offscreen image. Pass * to each slidescroll_item object its Vector index, the index is used by the object to calculate its * y coordinate. */ void setUpOffscreen() { int height = (navItemVector.size()+1)*lineSpace; if(height < nc_height) height = nc_height; Image offscreen2 = createImage(width, height); Graphics offscreeng2 = offscreen2.getGraphics(); offscreeng2.setColor(getBackground()); offscreeng2.fillRect(0,0, width, height); offscreeng2.drawImage(offscreen, 0, 0, null); offscreen = offscreen2; offscreeng = offscreen.getGraphics(); offscreeng2.dispose(); offscreen2 = null; Enumeration enum = navItemVector.elements(); slidescroll_item savItem = null; int i = 0; while (enum.hasMoreElements()) { slidescroll_item navItem = (slidescroll_item)enum.nextElement(); if(savItem != navItem) { i = navItem.drawLines(offscreeng, i, false); savItem = navItem; } } recalcScrollBar(); drawScrollBar(); } /** * This method is called once to open up the tree to a user specified node at startup. The first line in * treeIndex.txt is a path to the node that will be opened. To open a node, simulate a user click by * "throwing" a MOUSE_DOWN event. */ void openTree() { if(openPath == null) return; Date date = new Date(); StringTokenizer t = new StringTokenizer(openPath, ";"); while(t.hasMoreTokens()) { int i = findInNavItemVector(t.nextToken()); if(i >= 0) { lastLineIndex = i; i = lineSpace * i; i = i + lineSpace/2; myMousePressed(1, i); mouseDown = false; } } } /** * Scan each slidescroll_item object for the passed String and return the matching object. */ private int findInNavItemVector(String thisItemName) { for (int i = 0; i < navItemVector.size(); i++) { slidescroll_item navItem = (slidescroll_item)navItemVector.elementAt(i); if(thisItemName.equals(navItem.thisItemName)) return i; } return -1; } /** * This method will read the "link" param tags and insert them into the linkVector. */ private void getParmLink() { int i = 1; String parm = ns.getParameter("link" + i); while(parm != null) { linkVector.addElement(parm); i++; parm = ns.getParameter("link" + i); } } /** * This method will read the "index" param tags and insert them into the linkVector. */ private void getParmIndex() { int i = 1; String parm = ns.getParameter("index" + i); while(parm != null) { indexVector.addElement(parm); i++; parm = ns.getParameter("index" + i); } } /** * Search the linkVector for the passed name and set global variables childLink, and childTarget. */ private void getLink(String ItemName) { String vectorElement = null; String temp = ""; StringTokenizer t; Enumeration e = linkVector.elements(); childLink = null; int tempInt; nameValueParameters = ""; while(e.hasMoreElements()){ vectorElement = (String)e.nextElement(); t = new StringTokenizer(vectorElement, ";"); temp = t.nextToken(); if(ItemName.equals(temp)) { childLink = t.nextToken(); childTarget = null; while(t.hasMoreTokens()) childTarget = t.nextToken(); tempInt = childLink.indexOf("?"); if(tempInt < 0) return; nameValueParameters = childLink.substring(tempInt, childLink.length()); childLink = childLink.substring(0, tempInt); return; } } return; } /** * This method is called when the mouse is moved over the canvas. */ public void mouseMoved(MouseEvent e) { int x = e.getX(); int y = e.getY(); if(mouseDown) return; y = y -this.y; lineSelect = y/lineSpace; lineSelect = findFirst(lineSelect); lastLineIndex = findFirst(lastLineIndex); if(lastLineIndex >= 0 ) { slidescroll_item navItem = (slidescroll_item)navItemVector.elementAt(lastLineIndex); navItem.drawLines(offscreeng, lastLineIndex, false); } if(lineSelect < 0 || lineSelect >= navItemVector.size()) { setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); lastLineIndex = -1; ns.showStatus(""); repaint(); return; } slidescroll_item navItem = (slidescroll_item)navItemVector.elementAt(lineSelect); if(x < navItem.xpos-15 || x > width) { setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); lastLineIndex = -1; ns.showStatus(""); repaint(); return; } lineDown = lineSpace * (lineSelect+1); if(!navItem.text.trim().equals("")) setCursor(new Cursor(Cursor.HAND_CURSOR)); else setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); navItem.drawLines(offscreeng, lineSelect, true); repaint(); showTheStatus(navItem); lastLineIndex = lineSelect; return; } /** * This method will search the navItemVector for the first occurance of the passed object, and return the index. */ private int findFirst(int item) { if(item < 0 || item >= navItemVector.size()) return item; slidescroll_item searchItem = (slidescroll_item)navItemVector.elementAt(item); slidescroll_item navItem; for (int i = 0; i < navItemVector.size(); i++){ navItem = (slidescroll_item)navItemVector.elementAt(i); if(searchItem == navItem) return i; } return item; } /** * This method is called when the mouse is pressed. */ public void mousePressed(MouseEvent e) { if(me != null && (e.getWhen() == me.getWhen())) return; int y = e.getY(); int x = e.getX(); myMousePressed(x, y); me = e; } /** * This method is called when the mouse is released. */ public void mouseReleased(MouseEvent e) { if(lastLineIndex < 0 || lastLineIndex >= navItemVector.size()) return; return; } public void myMousePressed(int x, int y) { mousedx = x; mousedy = y; if(lastLineIndex < 0 || lastLineIndex >= navItemVector.size()) return; slidescroll_item navItem = (slidescroll_item)navItemVector.elementAt(lastLineIndex); if(navItem.text.trim().equals("")) return; if(menuSavItem != null) { menuSavItem.forcecHighlited = false; menuSavItem.drawLines(offscreeng, menuSavIndex, false); menuSavItem = null; } if(linkSavItem != null) { linkSavItem.forcecHighlited = false; linkSavItem.drawLines(offscreeng, linkSavIndex, false); linkSavItem = null; } if(navItem.childVector.size() <= 0) { linkSavIndex = lastLineIndex; linkSavItem = navItem; navItem.forcecHighlited = true; navItem.drawLines(offscreeng, lastLineIndex, true); repaint(); jumpToUrl(navItem.link, navItem.target); return; } int itemsScrolledUp = 0; navItem.forcecHighlited = true; menuSavItem = navItem; boolean savOpen = navItem.open; //save this for later //scan through currently displayed items and close any open items before we scroll down the //selected item. slidescroll_item savItem = null; for(int i = 0; i < navItemVector.size(); i++) { slidescroll_item navItem2 = (slidescroll_item)navItemVector.elementAt(i); if(savItem == null || savItem != navItem2) { //if a label wrapped, there will be multiple objects of //the same item in navItemVector, one for each line of //text. do this check only for the 1st found. //check to see if this item should scroll up. itemsScrolledUp = navItem2.checkToScrollUp(i, lastLineIndex); //was this item scrolled up? if(itemsScrolledUp >= 0) { //yes, was the selected item after the item that scrolled up? if(lastLineIndex > i) { //yes, then the selected item also scrolled up, recalculate its index and y coordinance. setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); lastLineIndex = lastLineIndex -itemsScrolledUp; } break; } } savItem = navItem2; } //Only scroll down items that started out closed at the beginning of this method. if(!savOpen) //closed? navItem.scrollDownChildren(lastLineIndex); //If the selected item is now open, save its index. if(navItem.open) menuSavIndex = lastLineIndex; else { menuSavItem = null; navItem.forcecHighlited = false; } //Decide if the mouse is now over a line, and change cursor to a hand. int temp = y/lineSpace; if(temp >= 0 && temp <= navItemVector.size()-1) { slidescroll_item navItem3 = (slidescroll_item)navItemVector.elementAt(temp); if(!navItem3.text.equals("")) setCursor(new Cursor(Cursor.HAND_CURSOR)); } return; } /** * This method is called when the mouse exits the canvas. */ public void mouseExited(MouseEvent e) { mouseexit = true; if(lastLineIndex >= 0) { slidescroll_item navItem = (slidescroll_item)navItemVector.elementAt(lastLineIndex); navItem.drawLines(offscreeng, lastLineIndex, false); repaint(); ns.showStatus(""); } lineSelect = -1; lastLineIndex = -1; setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); return ; } void showTheStatus(slidescroll_item navItem) { String theUrl = ""; if(navItem.link == null) theUrl = ""; else theUrl = navItem.link; if(!theUrl.trim().equals("")) ns.showStatus(theUrl); else if(navItem.childVector.size() > 0) ns.showStatus(navItem.text.trim()); else ns.showStatus(""); } /** * This method will display the document associated with the passed URL in the passed HTML frame. */ private void jumpToUrl(String theUrl, String target) { if(theUrl == null || theUrl.trim().equals("")) return; if(target == null) target = this.target; try { URL urlToGoto = new URL(theUrl); ns.getAppletContext().showDocument(urlToGoto, target); } catch (MalformedURLException e) {e.printStackTrace();} } //-------------------------------------------------------------------------------------- // Invoked when the mouse has been clicked on a component. //-------------------------------------------------------------------------------------- public void mouseClicked(MouseEvent e) {} //-------------------------------------------------------------------------------------- // Invoked when the mouse enters a component. //-------------------------------------------------------------------------------------- public void mouseEntered(MouseEvent e) { mouseexit = false; } } // end of class