/* QuickMenu: Consists of two button images (normal and highligthed) as well as a simple menu. Copyright Mike Horton 1996 horton@eecs.berkeley.edu. Permission is granted to do use and distribute this code free of charge */ import java.awt.*; import java.net.URL; import java.net.MalformedURLException; public class QuickMenu extends java.applet.Applet { Image offscreenImg; Graphics offscreenG; Image button; // the button graphic Image button2; // the highlighted graphic Color bkgcolor; // the background color Color menucolor; // the menu outline color MediaTracker tracker; // media tracker to monitor loading of images int ybutton = 0, xbutton = 0; // the y-location of the button-gif int buttonwidth, buttonheight; boolean inbutton = false, inmenu = false; // button display off and menu off QMenuLink menulinks[]; // individual menu entries with URL and text position String menustyle; // menustyle, pop from up, down side int xmenu = 0, ymenu = 0; // the top right corner of the menu int menuwidth = 0, menuheight = 0; // the height and width of the menu private int numrows = 0; // number of rows private int menurowspace = 20; // menu rowspacing int menuselect = -1; // nothing selected in menu public void init() { offscreenImg = createImage(this.size().width, this.size().height); offscreenG = offscreenImg.getGraphics(); // Get the menu entries while(getParameter("menu_link"+this.numrows) != null) { ++this.numrows; } String names[] = new String[this.numrows]; String dests[] = new String[this.numrows]; for (int i = 0; i < this.numrows; ++i) { ParamString tmp_s = new ParamString(getParameter("menu_link"+i)); names[i] = tmp_s.arg(1); dests[i] = tmp_s.arg(2); } // Create menulink objects for each entry menulinks = new QMenuLink[this.numrows]; for (int i = 0; i < numrows; ++i) { menulinks[i] = new QMenuLink(this, names[i], dests[i], 0, 0); } // Calculate the height/width of the menu based on the length and number of menu entries int curlen = 0; for (int i = 0; i < this.numrows; ++i) { curlen = menulinks[i].width(offscreenG); if (curlen > this.menuwidth) { this.menuwidth = curlen; } } this.menuwidth += 10; this.menuheight = this.numrows * this.menurowspace; // Load the images for the button animation button = getImage(getCodeBase(), getParameter("buttonup")); button2 = getImage(getCodeBase(), getParameter("buttondown")); // Create MediaTracker to make sure images load before starting tracker = new MediaTracker(this); tracker.addImage(button, 0); tracker.addImage(button2,0); try { tracker.waitForAll(); } catch (InterruptedException e) { System.out.println("Error waiting for images to load"); } // Set the button height and width buttonwidth = button.getWidth(this); buttonheight = button.getHeight(this); // Get and set the menu position menustyle = new String(getParameter("menu_position")); if (menustyle != null) { if (menustyle.equals("top")) { this.xmenu = (int) (this.size().width / 2 - this.menuwidth / 2); this.ymenu = this.buttonheight - 2; this.xbutton = (int) (this.size().width / 2 - this.buttonwidth / 2); this.ybutton = 0; } else if (menustyle.equals("bottom")) { this.xmenu = (int) (this.size().width / 2 - this.menuwidth/ 2); this.ymenu = this.size().height - this.buttonheight - this.menuheight; this.xbutton = (int) (this.size().width / 2 - this.buttonwidth / 2); this.ybutton = this.size().height - this.buttonheight - 1; } else if (menustyle.equals("side")) { this.xmenu = this.buttonwidth - 2; this.ymenu = (int) (this.size().height / 2 - this.menuheight / 2); this.xbutton = 0; this.ybutton = (int) (this.size().height / 2 - this.buttonheight / 2); } else { this.xmenu = this.buttonwidth - 2; this.ymenu = (int) (this.size().height / 2 - this.menuheight / 2); this.xbutton = 0; this.ybutton = (int) (this.size().height / 2 - this.buttonheight / 2); } } else { this.xmenu = this.buttonwidth - 2; this.ymenu = (int) (this.size().height / 2 - this.menuheight / 2); this.xbutton = 0; this.ybutton = (int) (this.size().height / 2 - this.buttonheight / 2); } // Reposition the menulinks for (int i = 0; i < this.numrows; ++i) { menulinks[i].x = xmenu; menulinks[i].y = ymenu + i * menurowspace; } // Set the background colors if (getParameter("bkg_color") != null) { ParamString c = new ParamString(getParameter("bkg_color")); bkgcolor = new Color(Integer.parseInt(c.arg(1)), Integer.parseInt(c.arg(2)), Integer.parseInt(c.arg(3))); } else { // Default to white bkgcolor = new Color(255,255,255); } setBackground(bkgcolor); if (getParameter("menu_color") != null) { ParamString c = new ParamString(getParameter("menu_color")); menucolor = new Color(Integer.parseInt(c.arg(1)), Integer.parseInt(c.arg(2)), Integer.parseInt(c.arg(3))); } else { // Default to black menucolor = new Color(0,0,0); } } public void start() { inbutton = false; inmenu = false; setBackground(bkgcolor); menuselect = -1; for (int i = 0; i < this.numrows; ++i) { menulinks[i].unhighlight(); } repaint(); } public void paint(Graphics g) { // Menu and button off, draw base button if (!inbutton && !inmenu) { offscreenG.setColor(getBackground()); offscreenG.fillRect(0,0,this.size().width, this.size().height); offscreenG.drawImage(button, xbutton, ybutton, this); } // draw menu links else { offscreenG.drawImage(button2, xbutton, ybutton, this); drawframe(offscreenG); for (int i = 0; i < this.numrows; ++i) { menulinks[i].paint(offscreenG); } } // copy offscreen graphics object to screen g.drawImage(offscreenImg,0,0,this); } public boolean mouseMove(Event evt, int x, int y) { // Transition into Button area, turn button & menu display on if ( inButton(x,y) && (inbutton == false) && (inmenu == false)) { inbutton = true; inmenu = true; repaint(); return true; } // Transistion out of Button and turn off display else if (!inButton(x,y) && !inMenu(x,y) && (inbutton==true)) { inbutton=false; inmenu = false; // Check for a highlighted menuitem and dehighlight it if (menuselect != -1) { menulinks[menuselect].unhighlight(); menuselect = -1; } repaint(); return true; } // Transition into menu when menu is on else if (inMenu(x,y) && inmenu == true) { // Transition into an unselected menulink if (inMenuLink(x,y) != menuselect) { if (menuselect == -1) { menuselect = inMenuLink(x,y); menulinks[menuselect].highlight(); repaint(); return true; } else { menulinks[menuselect].unhighlight(); menuselect = inMenuLink(x,y); menulinks[menuselect].highlight(); repaint(); return true; } } return true; } // Transition out of menu and turn off display else if (!inMenu(x,y) && inmenu == true && menuselect != -1) { menulinks[menuselect].unhighlight(); menuselect = -1; repaint(); return true; } else { return true; } } // Mousebutton pressed while link highlighted -> jump to link public boolean mouseDown(Event evt, int x, int y) { if (menuselect == -1) return true; else menulinks[menuselect].select(); return true; } // Draw menu outline void drawframe(Graphics g) { g.setColor(menucolor); g.drawRect(xmenu,ymenu,menuwidth,menuheight); g.drawLine(xmenu,ymenu+menurowspace, xmenu+menuwidth, ymenu+menurowspace); } // inButton boundary ? private boolean inButton(int x, int y) { if ((x > xbutton) && (x < xbutton + buttonwidth) && (y > ybutton) && (y < ybutton+buttonheight)) return true; else return false; } // inMenu boundary ? private boolean inMenu(int x, int y) { if ((x > xmenu) && (x < xmenu+menuwidth) && (y > ymenu) && (y < ymenu + menuheight)) return true; else return false; } // which link selected ? -1 is none 0 is first entry ... private int inMenuLink(int x, int y) { int cur = (int) ((y-ymenu) / menurowspace); if (cur > this.numrows-1) return this.numrows-1; else return cur; } } /* A text link within the QuickMenu. Text is highlighted red. */ class QMenuLink { QuickMenu outerparent; // calling environment required for switching pages String name; // Name of menulink URL url; // Destination of menulink Color color; // text color int x,y; // x,y location of bottom left corner of menulink text Font f; // menulink font FontMetrics fm; // font metrics object // Link constructor QMenuLink(QuickMenu target, String name, String theURL, int x, int y) { this.outerparent = target; this.name = name; this.x = x; this.y = y; try { this.url = new URL(theURL); } catch ( MalformedURLException e) { System.out.println("Bad URL: " + theURL); } f = new Font("Arial", Font.BOLD, 14); } // Draw menu link text public void paint(Graphics g) { g.setFont(f); g.setColor(color); g.drawString(this.name, this.x+5, this.y+17); } public void highlight() { color = Color.red; } public void unhighlight() { color = this.outerparent.menucolor; } // Jump to URL public void select() { outerparent.getAppletContext().showDocument(url); } public int width(Graphics g) { fm = g.getFontMetrics(this.f); return fm.stringWidth(this.name); } } class ParamString { String s; ParamString(String str) { s = new String(str); } public String arg(int number) { int arg_cnt = 0, i =0, ind = 0; int tmp = s.length(); for (i = 0; i < tmp; ++i) { if (s.startsWith("|",i)) { arg_cnt++; if (arg_cnt == number) break; else ind = i+1; } } return new String(s.substring(ind,i)); } }