// A button or menu item that serves as a hyperlink. // // Use this applet by including text similar to the following in your HTML file: // // // // // // // // // // // // // //... // // java // // // Applet parameters: //ZZZ update this description. // BGCOLOR - the background color for the applet, // in the same format as HTML BODY BGCOLOR (e.g., #ff0000 = red) // FGCOLOR - the foreground (text) color, // in the same format as HTML BODY TEXT (e.g., #ff0000 = red) // FONTNAME - name of the font to draw in, e.g., "Helvetica". // See the Java spec for standard font names. // FONTSIZE - the size (in points) to draw text in, e.g., 12 // FONTSTYLE - a set of styles to use: 'B' = BOLD, 'I' = ITALIC. "" = PLAIN. import java.awt.*; import java.applet.*; import java.io.*; import java.net.*; import java.awt.image.*; public class link extends java.applet.Applet { final int maxItems = 100; // maximum number of items in a menu. final String dflFont = "Helvetica"; final int dflFontsize = 12; final int dflFontstyle = Font.PLAIN; final Color dflBgColor = Color.lightGray; final Color dflBgColorOver = Color.white; final Color dflBgColorDown = Color.black; final Color dflFgColor = Color.darkGray; final Color dflFgColorOver = Color.black; final Color dflFgColorDown = Color.white; Color bgColor; // the background color for normal display. Color bgColorOver; // ditto for mouse-over. Color bgColorDown; // ditto for mouse-down. Color fgColor; // the foreground (text) color for normal display. Color fgColorOver; // ditto for mouse-over. Color fgColorDown; // ditto for mouse-down. Font theFont; // the font to use. int itemWidth; // supplied width of each item (0 == no width supplied) int itemHeight; // ditto for height. Image imageNorm; // normal (no mouse) image of the entire menu (or null) Image imageOver; // image for when the mouse is over an item (or null). Image imageDown; // image for when the mouse is down in an item (or null). MediaTracker trackImage; // to monitor loading of our images. String labelText[]; // text of each label (null or empty == no label supplied) String urlText[]; // text of each URL (null or empty == no URL supplied) Dimension oldSize; // our applet's previous (current) size. int rWidth; // calculated width of each menu item. int rHeight; // calculated height of each menu item. int numItems; // calculated number of items in the menu. Point lastMouse; // last known pixel position of the mouse within our menu. boolean isDown; // "The mouse is down" Point downMouse; // last position of the mouse-down. // Check to see if our size has changed, // returning true if it has, false otherwise. // If the size has changed, update our size-dependent data. boolean checkSize() { Dimension winSize; // our applet's screen size. winSize = this.size(); if (winSize.height == oldSize.height && winSize.width == oldSize.width) { return false; } // our applet size has changed. oldSize = winSize; // find the dimensions of a menu item. rWidth = itemWidth; if (rWidth == 0) { rWidth = winSize.width; } rHeight = itemHeight; if (rHeight == 0) { rHeight = winSize.height; } // Find the number of items in the menu. if (rWidth <= 0 || rHeight <= 0) { numItems = 0; } else { numItems = ((winSize.width + rWidth - 1) / rWidth) * ((winSize.height + rHeight - 1) / rHeight); if (numItems < 0) { numItems = 0; } if (numItems > maxItems) { numItems = maxItems; } } return false; } // Convert the given coordinates to the index of the item containing that point, // or -1 if there is no such item. int ptToItem(int x, int y) { int xItem; // the x coordinate of the item. int yItem; // ditto for y. int xItems; // number of items per line. checkSize(); if (!(0 <= x && x < oldSize.width) || !(0 <= y && y < oldSize.height)) { return -1; } xItems = (oldSize.width + rWidth - 1) / rWidth; xItem = x / rWidth; yItem = y / rHeight; return (xItem + yItem * xItems); } public void init() { String fontName; // name of the font to use. int fontSize; // font size (points) to use. int fontStyle; // the style (e.g., BOLD) to use. String str; oldSize = new Dimension(-1, -1); lastMouse = new Point(-1, -1); downMouse = new Point(-1, -1); isDown = false; itemWidth = 0; itemHeight = 0; labelText = new String[maxItems]; for (int i = 0; i < maxItems; ++i) { labelText[i] = ""; str = getParameter("LABEL" + Integer.toString(i, 10)); if (str != null) { labelText[i] = str; } } urlText = new String[maxItems]; for (int i = 0; i < maxItems; ++i) { urlText[i] = ""; str = getParameter("LINK" + Integer.toString(i, 10)); if (str != null) { urlText[i] = str; } } // Grab our parameters: // bgcolor - the background color, e.g., "#ffff00" // fgcolor - the foreground color, e.g., "#ff0000" // fontname - the name of the font to write in, e.g., "Helvetica" // fontsize - the size (in points) to use, e.g., "12" // fontstyle - the style of font (e.g., "BI" for BOLD and ITALIC). // time - the date & time + timezone to convert, e.g., "12 May 1997 5:30pm EDT" str = getParameter("ITEMWIDTH"); if (str == null) { itemWidth = 0; } else { try { itemWidth = Integer.parseInt(str, 10); } catch (NumberFormatException e) { itemWidth = 0; } } str = getParameter("ITEMHEIGHT"); if (str == null) { itemHeight = 0; } else { try { itemHeight = Integer.parseInt(str, 10); } catch (NumberFormatException e) { itemHeight = 0; } } str = getParameter("BGCOLOR"); if (str == null) { bgColor = dflBgColor; } else { try { if (str.charAt(0) == '#') { bgColor = new Color(Integer.parseInt(str.substring(1), 16)); } else { bgColor = new Color(Integer.parseInt(str, 10)); } } catch (NumberFormatException e) { bgColor = dflBgColor; } } str = getParameter("BGCOLOROVER"); if (str == null) { bgColorOver = dflBgColorOver; } else { try { if (str.charAt(0) == '#') { bgColorOver = new Color(Integer.parseInt(str.substring(1), 16)); } else { bgColorOver = new Color(Integer.parseInt(str, 10)); } } catch (NumberFormatException e) { bgColorOver = dflBgColorOver; } } str = getParameter("BGCOLORDOWN"); if (str == null) { bgColorDown = dflBgColorDown; } else { try { if (str.charAt(0) == '#') { bgColorDown = new Color(Integer.parseInt(str.substring(1), 16)); } else { bgColorDown = new Color(Integer.parseInt(str, 10)); } } catch (NumberFormatException e) { bgColorDown = dflBgColor; } } str = getParameter("FGCOLOR"); if (str == null) { fgColor = dflFgColor; } else { try { if (str.charAt(0) == '#') { fgColor = new Color(Integer.parseInt(str.substring(1), 16)); } else { fgColor = new Color(Integer.parseInt(str, 10)); } } catch (NumberFormatException e) { fgColor = dflFgColor; } } str = getParameter("FGCOLOROVER"); if (str == null) { fgColorOver = dflFgColorOver; } else { try { if (str.charAt(0) == '#') { fgColorOver = new Color(Integer.parseInt(str.substring(1), 16)); } else { fgColorOver = new Color(Integer.parseInt(str, 10)); } } catch (NumberFormatException e) { fgColorOver = dflFgColor; } } str = getParameter("FGCOLORDOWN"); if (str == null) { fgColorDown = dflFgColorDown; } else { try { if (str.charAt(0) == '#') { fgColorDown = new Color(Integer.parseInt(str.substring(1), 16)); } else { fgColorDown = new Color(Integer.parseInt(str, 10)); } } catch (NumberFormatException e) { fgColorDown = dflFgColor; } } str = getParameter("IMAGE"); if (str == null) { imageNorm = null; } else { imageNorm = getImage(getDocumentBase(), str); // (note: just STARTS loading here) } str = getParameter("IMAGEOVER"); if (str == null) { imageOver = null; } else { imageOver = getImage(getDocumentBase(), str); } str = getParameter("IMAGEDOWN"); if (str == null) { imageDown = null; } else { imageDown = getImage(getDocumentBase(), str); } fontName = getParameter("FONTNAME"); if (fontName == null) { fontName = dflFont; } str = getParameter("FONTSIZE"); if (str == null) { fontSize = dflFontsize; } else { try { fontSize = Integer.parseInt(str, 10); } catch (NumberFormatException e) { fontSize = dflFontsize; } } str = getParameter("FONTSTYLE"); if (str == null) { fontStyle = dflFontstyle; } else { fontStyle = Font.PLAIN; if (str.indexOf('B') != -1 || str.indexOf('b') != -1) { fontStyle |= Font.BOLD; } if (str.indexOf('I') != -1 || str.indexOf('i') != -1) { fontStyle |= Font.ITALIC; } } theFont = new Font(fontName, fontStyle, fontSize); // Prepare to track the loading of the images. trackImage = new MediaTracker(this); if (imageNorm != null) { trackImage.addImage(imageNorm, 1); } if (imageOver != null) { trackImage.addImage(imageOver, 2); } if (imageDown != null) { trackImage.addImage(imageDown, 3); } // wait for the images to load. try { if (imageNorm != null) { trackImage.waitForID(1); } if (imageOver != null) { trackImage.waitForID(2); } if (imageDown != null) { trackImage.waitForID(3); } } catch (InterruptedException e) { } } public void destroy() { if (imageNorm != null) { imageNorm.flush(); } if (imageOver != null) { imageOver.flush(); } if (imageDown != null) { imageDown.flush(); } } public void start() { repaint(); } public void stop() { } public boolean mouseUp(Event evt, int x, int y) { int downItem; // index of the item the mouse went down in. int upItem; // index of the item the mouse went up in. isDown = false; mouseMovedTo(x, y); repaint(); // find where the mouse was clicked. checkSize(); downItem = ptToItem(downMouse.x, downMouse.y); upItem = ptToItem(lastMouse.x, lastMouse.y); // If this isn't a valid click, return now. if (downItem != upItem || downItem == -1) { return false; } // Follow the URL of that item. if (urlText[downItem].length() > 0) { try { getAppletContext().showDocument(new URL(getDocumentBase(), urlText[downItem])); } catch (MalformedURLException e) { } } return false; } public boolean mouseDown(Event evt, int x, int y) { isDown = true; downMouse.x = x; downMouse.y = y; mouseMovedTo(x, y); repaint(); return false; } public boolean mouseMove(Event evt, int x, int y) { mouseMovedTo(x, y); return false; } // An exit is essentially a move outside our menu. public boolean mouseExit(Event evt, int x, int y) { mouseMovedTo(-1, -1); return false; } public boolean mouseDrag(Event evt, int x, int y) { mouseMovedTo(x, y); return false; } // Called when the mouse has moved, // this method decides whether we need to repaint the screen as a result. void mouseMovedTo(int x, int y) { int oldItem; // item the mouse used to be in. int newItem; // item the mouse is now in. oldItem = ptToItem(lastMouse.x, lastMouse.y); newItem = ptToItem(x, y); lastMouse.x = x; lastMouse.y = y; if (oldItem != newItem) { repaint(); } } // Overridden so we don't erase before repainting, // to reduce flicker. public void update(Graphics g) { paint(g); } public void paint(Graphics gScreen) { FontMetrics fm; // measurements of the current font. Rectangle r; // bounds of the current menu item. Graphics g; // a temporary graphics context, for clipping. Image offscreen; // an offscreen bitmap. Graphics gOrig; // its graphic context. checkSize(); offscreen = createImage(oldSize.width, oldSize.height); gOrig = offscreen.getGraphics(); r = new Rectangle(0, 0, 10, 10); // Draw each item. r.reshape(0, 0, rWidth, rHeight); for (int itemNum = 0; itemNum < numItems; ++itemNum) { // make a new graphics context, clipped to this menu item. g = gOrig.create(); g.clipRect(r.x, r.y, r.width, r.height); g.setFont(theFont); fm = g.getFontMetrics(); // Choose which state this item is in. if (!r.inside(lastMouse.x, lastMouse.y) || (isDown && !r.inside(downMouse.x, downMouse.y))) { // the mouse is outside this item // or was pressed outside this item. // Show Normal. if (imageNorm != null) { g.drawImage(imageNorm, 0, 0, this); } else { g.setColor(bgColor); g.fillRect(r.x, r.y, r.width, r.height); } if (labelText[itemNum].length() > 0) { g.setColor(fgColor); g.drawString(labelText[itemNum], r.x + 2, r.y + r.height - (fm.getLeading() + fm.getDescent())); } } else { // the mouse is inside this item and wasn't pressed outside this item. if (isDown) { // the mouse is down inside this item. // Show Down. if (imageDown != null) { g.drawImage(imageDown, 0, 0, this); } else { g.setColor(bgColorDown); g.fillRect(r.x, r.y, r.width, r.height); } if (labelText[itemNum].length() > 0) { g.setColor(fgColorDown); g.drawString(labelText[itemNum], r.x + 2, r.y + r.height - (fm.getLeading() + fm.getDescent())); } } else { // the mouse isn't down, but is inside this item. // Show Over. if (imageOver != null) { g.drawImage(imageOver, 0, 0, this); } else { g.setColor(bgColorOver); g.fillRect(r.x, r.y, r.width, r.height); } if (labelText[itemNum].length() > 0) { g.setColor(fgColorOver); g.drawString(labelText[itemNum], r.x + 2, r.y + r.height - (fm.getLeading() + fm.getDescent())); } } } // Move to the next item. r.move(r.x + rWidth, r.y); if (r.x >= oldSize.width) { r.move(0, r.y + rHeight); } g.dispose(); g = null; } // Draw the offscreen bitmap onto the screen. gScreen.drawImage(offscreen, 0, 0, this); gOrig = null; offscreen.flush(); offscreen = null; } }