import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import utilities.*; import utilities.beans.*; import utilities.files.*; public class ImageMap extends VisibleCanvas implements MouseListener, MouseMotionListener, TextLineProcessor { protected String image; // filename protected Image imageImage; // the imagemap itself protected int width, height; // imagemap width and height protected Vector hotZones; // database of rectangular hot zones protected Vector zoneListeners; // each zone has 1 listener //------------------------------------------------------------------- // ImageMap Constructor //------------------------------------------------------------------- public ImageMap() { image = null; width = height = 40; addMouseListener(this); addMouseMotionListener(this); zoneListeners = new Vector(); } //------------------------------------------------------------------- // set()/get() for 'Image' property //------------------------------------------------------------------- public void setImage(String imageMapFilename) { String baseName; if ( ! (imageMapFilename.endsWith(".gif") || imageMapFilename.endsWith(".jpg")) ) { System.out.println("ImageMap: filename has to be .gif or .jpg"); return; } baseName = imageMapFilename.substring(0, imageMapFilename.length()-4); if ( ! loadMap(baseName + ".map")) { System.out.println("ImageMap: Failed to load map."); return; } imageImage = loadImage(imageMapFilename); if ( imageImage == null ) { System.out.println("ImageMap: null image"); return; } int newWidth = imageImage.getWidth(this); int newHeight = imageImage.getHeight(this); // if the image is a different size compared to prev image, // force Container to layout itself using our new dimensions. if ( newWidth != width || newHeight != height ) { width = newWidth; height = newHeight; Container container = getParent(); container.setSize(container.getPreferredSize()); container.validate(); } else { repaint(); } this.image = imageMapFilename; } public String getImage() { return image; } //------------------------------------------------------------------- // Load a map. Maps are simple ASCII files containing rectangle specs like // x1,y1 x2,y2 //------------------------------------------------------------------- protected boolean loadMap(String mapFilename) { FileInputStream fin; BufferedInputStream input; boolean ok; try { fin = new FileInputStream(mapFilename); } catch (FileNotFoundException noSuchMapFile) { System.out.println(noSuchMapFile); return false; } hotZones = new Vector(); input = new BufferedInputStream(fin); ok = TextFileGrinder.processUsing(input, this); try { fin.close(); } catch (IOException ignored) { System.out.println("ImageMap: Could not close " + mapFilename); } return ok; } //------------------------------------------------------------------- // TextLineProcessor interface implementation //------------------------------------------------------------------- public boolean processTextLine(String line) { StringTokenizer st; String num; int x1,y1, x2,y2; Rectangle rect; if ( line == null || line.equals("")) { return true; } st = new StringTokenizer(line, ", "); while (st.hasMoreTokens()) { num = st.nextToken(); x1 = Integer.parseInt(num); num = st.nextToken(); y1 = Integer.parseInt(num); num = st.nextToken(); x2 = Integer.parseInt(num); num = st.nextToken(); y2 = Integer.parseInt(num); // create Rectangle from file's entry rect = new Rectangle(x1,y1, x2-x1, y2-y1); // add rectangle to list of "hot zones" hotZones.addElement(rect); } return true; } //------------------------------------------------------------------- // See if a point falls inside any rectangle in our "hot zone" list //------------------------------------------------------------------- protected int insideWhichZone(int x, int y, Vector hotZones) { Rectangle rect; // if rectangle map hasn't been initialized, ignore request if ( hotZones == null ) { return -1; } int i = 0; Enumeration rectIterator = hotZones.elements(); while ( rectIterator.hasMoreElements() ) { rect = (Rectangle) rectIterator.nextElement(); if ( rect.contains(x,y) ) { return i; } i++; } return -1; } //------------------------------------------------------------------- // Highlight zone if pointer hovers above one //------------------------------------------------------------------- protected void highlightZones(int x, int y) { int zoneIndex = insideWhichZone(x,y, hotZones); if ( zoneIndex != -1 ) { System.out.println("Pointer over zone " + zoneIndex); } } //------------------------------------------------------------------- // Overridden Component.update() and Component.paint() //------------------------------------------------------------------- public void update(Graphics g) { paint(g); } public void paint(Graphics g) { if ( imageImage != null ) { g.drawImage(imageImage, 0,0, this); } else { super.paint(g); } } //------------------------------------------------------------------- // Preferred size for our component //------------------------------------------------------------------- public Dimension preferredSize() { // 1.0-style return new Dimension(width, height); } public Dimension getPreferredSize() { // 1.1-style return preferredSize(); } //------------------------------------------------------------------- // MouseMotionListener interface methods //------------------------------------------------------------------- public void mouseDragged(MouseEvent mouseEvent) {} public void mouseMoved(MouseEvent mouseEvent) { int x,y; x = mouseEvent.getX(); y = mouseEvent.getY(); highlightZones(x,y); } //------------------------------------------------------------------- // MouseListener interface methods // If user clicks inside a hot zone, then notify the listener // associated with this hot zone. //------------------------------------------------------------------- public void mouseClicked(MouseEvent mouseEvent) { int x,y; int zoneIndex; x = mouseEvent.getX(); y = mouseEvent.getY(); zoneIndex = insideWhichZone(x,y, hotZones); if ( zoneIndex == -1 ) { return; } System.out.println("Clicked in zone " + zoneIndex); // avoid ArrayIndexOutOfBoundsException if ( zoneListeners.size() <= zoneIndex) { return; } ActionListener listener = (ActionListener) zoneListeners.elementAt(zoneIndex); // if listener for this hot zone is present, notify it of click if ( listener != null ) { listener.actionPerformed(new ActionEvent(this, 0, "")); } } //------------------------------------------------------------------- public void mousePressed(MouseEvent mouseEvent) {} public void mouseReleased(MouseEvent mouseEvent) {} public void mouseEntered(MouseEvent mouseEvent) {} public void mouseExited(MouseEvent mouseEvent) {} //------------------------------------------------------------------- // ActionListener management methods //------------------------------------------------------------------- public void addActionListener(ActionListener listener) { zoneListeners.addElement(listener); } public void removeActionListener(ActionListener listener) { int listenerID; listenerID = zoneListeners.indexOf(listener); if ( listenerID != -1 ) { zoneListeners.setElementAt(null, listenerID); } } //------------------------------------------------------------------- // Load an image file (GIF or JPEG) //------------------------------------------------------------------- public static Image loadImage(String imageFilename) { Image image; image = Toolkit.getDefaultToolkit().getImage(imageFilename); // Use a mediatracker to wait until image is completely loaded MediaTracker tracker = new MediaTracker( new Canvas() ); tracker.addImage(image,0); try { tracker.waitForAll(); } catch (InterruptedException irq) { System.out.println("Mediatracker.waitForAll() interrupted in loadImage() !"); } return image; } //------------------------------------------------------------------- // ImageMap Self-Test code //------------------------------------------------------------------- public static void main (String[] args) { Frame window = new Frame("ImageMap Self-Test"); ImageMap im = new ImageMap(); window.add("Center", im); window.pack(); window.setVisible(true); MiscKit.delay(2000); System.out.println("setting imagemap"); im.setImage("rasta.gif"); MiscKit.delay(2000); } } // End of Class ImageMap