import java.applet.Applet; import java.awt.Canvas; import java.awt.Image; import java.awt.Point; import java.awt.Graphics; import java.awt.Color; import java.util.Vector; import java.awt.Event; import java.net.URL; /** * a Canvas subclass that accepts multiple * image specs, loads them, and displays * one of them at a time. (Note that a lot of * this code is a little looser than I would * normally write, to try to keep the resulting * .class file a little smaller) */ public class MultiImageDisplay extends Canvas { // fields -- accessible to this package int currentImage; Vector images; boolean drawlocations; Vector locations; Color pointColor; Color specialColor; Location specialLocation; static int MARGINS = 2; static int POINTSIZE = 6; static int TOLERANCE = 4; /** * constructor, accepts an integer telling * about how many images to expect. Giving * 0 means use default. */ public MultiImageDisplay(int expectNo) { currentImage = -1; if (expectNo == 0) expectNo = 6; images = new Vector(expectNo); locations = new Vector(expectNo); drawlocations = true; specialLocation = null; pointColor = Color.red; specialColor = new Color(60,75,255); } /** * paint function, paint the image and * maybe paint the locations also. */ public void paint(Graphics g) { Object co; super.paint(g); if (currentImage < 0 || currentImage >= images.size()) return; co = images.elementAt(currentImage); if (!(co instanceof Image)) return; if (g.drawImage((Image)co, MARGINS, MARGINS, this)) { drawLocationPoints(g); } return; } public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { boolean ret = super.imageUpdate(img,flags,x,y,w,h); if ((flags & ALLBITS) != 0) { drawLocationPoints(null); } return ret; } /** * draw location points as dots, if the * boolean flag drawlocations is set. */ public void drawLocationPoints(Graphics g) { Object lo; if (drawlocations == false) return; if (currentImage < 0 || currentImage >= images.size()) return; lo = locations.elementAt(currentImage); if (!(lo instanceof Vector)) return; Vector points = (Vector)lo; if (points.size() == 0) return; if (g == null) g = getGraphics(); int len = points.size(); for(int ix = 0; ix < len; ix++) { Location loc = (Location)(points.elementAt(ix)); if (loc == specialLocation) g.setColor(specialColor); else g.setColor(pointColor); if (loc.w() > 0 && loc.h() > 0) { g.drawRect(loc.x() + MARGINS, loc.y() + MARGINS, loc.w(), loc.h()); } else { g.fillOval((loc.x() - POINTSIZE/2) + MARGINS, (loc.y() - POINTSIZE/2) + MARGINS, POINTSIZE, POINTSIZE); } } return; } /** * look through the current list of Locations and * find first point near the given Point. */ public Location findLocationNear(Point p, int tol) { Object lo; Location ret; if (currentImage < 0 || currentImage >= images.size()) return null; lo = locations.elementAt(currentImage); if (!(lo instanceof Vector)) return null; Vector points = (Vector)lo; int len = points.size(); for(int ix = 0; ix < len; ix++) { ret = (Location)(points.elementAt(ix)); if (ret.within(p,tol)) return ret; } return null; } /** * this adds a new image to this MultiImageDisplay * canvas. The new image is supplied as a URL string, * which we translate into a URL and then load as an * image. We return the image object, or null if * any errors occurred. Note that the image will * we loaded in its own thread, so we cannot assume * that the height and width are correct at first. */ public Image addImage(Applet applet, String urlstr) { Image ret = null; URL url; try { url = new URL(applet.getDocumentBase(), urlstr); ret = applet.getImage(url); } catch (Exception e) { url = null; ret = null; } if (ret != null) { images.addElement(ret); if (currentImage < 0) { currentImage = 0; repaint(); } locations.addElement(new Vector(10)); } return ret; } /** * this adds a supplied Location to the current * image location vector, creating the vector if * necessary. we return the new Location object * so that the caller can set a name and description. */ public Location addLocation(String xy) { Object lo; if (currentImage < 0 || currentImage >= images.size()) return null; lo = locations.elementAt(currentImage); if (!(lo instanceof Vector)) return null; // this line might throw a NumberFormatException Location ret = new Location(xy); Vector points = (Vector)lo; points.addElement(ret); return ret; } /** * this method handles mouse down events by * calling action with the Location under the * mouse as an argument object. */ public boolean mouseDown(Event evt, int x, int y) { Location clicked = findLocationNear(new Point(x - MARGINS,y - MARGINS), TOLERANCE); return getParent().action(evt, clicked); } };