home *** CD-ROM | disk | FTP | other *** search
/ BUG 15 / BUGCD1998_06.ISO / aplic / jbuilder / jsamples.z / ImageMap.java < prev    next >
Text File  |  1997-07-30  |  13KB  |  455 lines

  1. // $Header: z:/admin/metro_examples/java/demo/ImageMap/rcs/ImageMap.java 1.1 1997/02/06 00:30:04 IPGIntel-2 Exp $ 
  2. /*
  3.  * @(#)ImageMap.java    1.8 96/12/06
  4.  *
  5.  * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
  6.  *
  7.  * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
  8.  * modify and redistribute this software in source and binary code form,
  9.  * provided that i) this copyright notice and license appear on all copies of
  10.  * the software; and ii) Licensee does not utilize the software in a manner
  11.  * which is disparaging to Sun.
  12.  *
  13.  * This software is provided "AS IS," without a warranty of any kind. ALL
  14.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  15.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  16.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  17.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  18.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  19.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  20.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  21.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  22.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  23.  * POSSIBILITY OF SUCH DAMAGES.
  24.  *
  25.  * This software is not designed or intended for use in on-line control of
  26.  * aircraft, air traffic, aircraft navigation or aircraft communications; or in
  27.  * the design, construction, operation or maintenance of any nuclear
  28.  * facility. Licensee represents and warrants that it will not use or
  29.  * redistribute the Software for such purposes.
  30.  */
  31.  
  32. import java.applet.Applet;
  33. import java.awt.Image;
  34. import java.awt.Graphics;
  35. import java.awt.Rectangle;
  36. import java.awt.MediaTracker;
  37. import java.util.StringTokenizer;
  38. import java.util.Vector;
  39. import java.util.Hashtable;
  40. import java.net.URL;
  41. import java.awt.image.ImageProducer;
  42. import java.awt.image.ImageFilter;
  43. import java.awt.image.CropImageFilter;
  44. import java.awt.image.FilteredImageSource;
  45. import java.net.MalformedURLException;
  46.  
  47. /**
  48.  * An extensible ImageMap applet class.
  49.  * The active areas on the image are controlled by ImageArea classes
  50.  * that can be dynamically loaded over the net.
  51.  *
  52.  * @author     Jim Graham
  53.  * @version     1.8, 12/06/96
  54.  */
  55. public class ImageMap extends Applet implements Runnable {
  56.     /**
  57.      * The unhighlighted image being mapped.
  58.      */
  59.     Image baseImage;
  60.  
  61.     /**
  62.      * The list of image area handling objects;
  63.      */
  64.     ImageMapArea areas[];
  65.  
  66.     /**
  67.      * The primary highlight mode to be used.
  68.      */
  69.     static final int BRIGHTER = 0;
  70.     static final int DARKER = 1;
  71.  
  72.     int hlmode = BRIGHTER;
  73.  
  74.     /**
  75.      * The percentage of highlight to apply for the primary highlight mode.
  76.      */
  77.     int hlpercent = 50;
  78.  
  79.     /**
  80.      * The MediaTracker for loading and constructing the various images.
  81.      */
  82.     MediaTracker tracker;
  83.  
  84.     /**
  85.      * Get a rectangular region of the baseImage highlighted according to
  86.      * the primary highlight specification.
  87.      */
  88.     Image getHighlight(int x, int y, int w, int h) {
  89.     return getHighlight(x, y, w, h, hlmode, hlpercent);
  90.     }
  91.  
  92.     /**
  93.      * Get a rectangular region of the baseImage with a specific highlight.
  94.      */
  95.     Image getHighlight(int x, int y, int w, int h, int mode, int percent) {
  96.     return getHighlight(x, y, w, h, new HighlightFilter(mode == BRIGHTER,
  97.                                 percent));
  98.     }
  99.  
  100.     /**
  101.      * Get a rectangular region of the baseImage modified by an image filter.
  102.      */
  103.     Image getHighlight(int x, int y, int w, int h, ImageFilter filter) {
  104.     ImageFilter cropfilter = new CropImageFilter(x, y, w, h);
  105.     ImageProducer prod = new FilteredImageSource(baseImage.getSource(),
  106.                              cropfilter);
  107.     return makeImage(prod, filter, 0);
  108.     }
  109.  
  110.     /**
  111.      * Make a filtered image based on another image.
  112.      */
  113.     Image makeImage(Image orig, ImageFilter filter) {
  114.     return makeImage(orig.getSource(), filter);
  115.     }
  116.  
  117.     /**
  118.      * Make a filtered image based on another ImageProducer.
  119.      */
  120.     Image makeImage(ImageProducer prod, ImageFilter filter) {
  121.     return makeImage(prod, filter,
  122.              (prod == baseImage.getSource()) ? 1 : 0);
  123.     }
  124.  
  125.     /**
  126.      * Make a filtered image based on another ImageProducer.
  127.      * Add it to the media tracker using the indicated ID.
  128.      */
  129.     Image makeImage(ImageProducer prod, ImageFilter filter, int ID) {
  130.     Image filtered = createImage(new FilteredImageSource(prod, filter));
  131.     tracker.addImage(filtered, ID);
  132.     return filtered;
  133.     }
  134.  
  135.     /**
  136.      * Add an image to the list of images to be tracked.
  137.      */
  138.     void addImage(Image img) {
  139.     tracker.addImage(img, 1);
  140.     }
  141.  
  142.     /**
  143.      * Parse a string representing the desired highlight to be applied.
  144.      */
  145.     void parseHighlight(String s) {
  146.     if (s == null) {
  147.         return;
  148.     }
  149.     if (s.startsWith("brighter")) {
  150.         hlmode = BRIGHTER;
  151.         if (s.length() > "brighter".length()) {
  152.         hlpercent = Integer.parseInt(s.substring("brighter".length()));
  153.         }
  154.     } else if (s.startsWith("darker")) {
  155.         hlmode = DARKER;
  156.         if (s.length() > "darker".length()) {
  157.         hlpercent = Integer.parseInt(s.substring("darker".length()));
  158.         }
  159.     }
  160.     }
  161.  
  162.     /**
  163.      * Initialize the applet. Get attributes.
  164.      *
  165.      * Initialize the ImageAreas.
  166.      * Each ImageArea is a subclass of the class ImageArea, and is
  167.      * specified with an attribute of the form:
  168.      *         areaN=ImageAreaClassName,arguments...
  169.      * The ImageAreaClassName is parsed off and a new instance of that
  170.      * class is created.  The initializer for that class is passed a
  171.      * reference to the applet and the remainder of the attribute
  172.      * string, from which the class should retrieve any information it
  173.      * needs about the area it controls and the actions it needs to
  174.      * take within that area.
  175.      */
  176.     public void init() {
  177.     String s;
  178.  
  179.     tracker = new MediaTracker(this);
  180.     parseHighlight(getParameter("highlight"));
  181.     introTune = getParameter("startsound");
  182.     baseImage = getImage(getDocumentBase(), getParameter("img"));
  183.     Vector areaVec = new Vector();
  184.     int num = 1;
  185.     while (true) {
  186.         ImageMapArea newArea;
  187.         s = getParameter("area"+num);
  188.         if (s == null) {
  189.         // Try rect for backwards compatibility.
  190.         s = getParameter("rect"+num);
  191.         if (s == null) {
  192.             break;
  193.         }
  194.         try {
  195.             newArea = new HighlightArea();
  196.             newArea.init(this, s);
  197.             areaVec.addElement(newArea);
  198.             String url = getParameter("href"+num);
  199.             if (url != null) {
  200.             s += "," + url;
  201.             newArea = new LinkArea();
  202.             newArea.init(this, s);
  203.             areaVec.addElement(newArea);
  204.             }
  205.         } catch (Exception e) {
  206.             System.out.println("error processing: "+s);
  207.             e.printStackTrace();
  208.             break;
  209.         }
  210.         } else {
  211.         try {
  212.             int classend = s.indexOf(",");
  213.             String name = s.substring(0, classend);
  214.             newArea = (ImageMapArea) Class.forName(name).newInstance();
  215.             s = s.substring(classend+1);
  216.             newArea.init(this, s);
  217.             areaVec.addElement(newArea);
  218.         } catch (Exception e) {
  219.             System.out.println("error processing: "+s);
  220.             e.printStackTrace();
  221.             break;
  222.         }
  223.         }
  224.         num++;
  225.     }
  226.     areas = new ImageMapArea[areaVec.size()];
  227.     areaVec.copyInto(areas);
  228.     checkSize();
  229.     }
  230.  
  231.     Thread aniThread = null;
  232.     String introTune = null;
  233.  
  234.     public void start() {
  235.     if (introTune != null)
  236.         try {
  237.         play(new URL(getDocumentBase(), introTune));
  238.         } catch (MalformedURLException e) {}
  239.     if (aniThread == null) {
  240.             aniThread = new Thread(this);
  241.             aniThread.setName("ImageMap Animator");
  242.             aniThread.start();
  243.     }
  244.     }
  245.  
  246.     public void run() {
  247.     Thread me = Thread.currentThread();
  248.     tracker.checkAll(true);
  249.     for (int i = areas.length; --i >= 0; ) {
  250.         areas[i].getMedia();
  251.     }
  252.     me.setPriority(Thread.MIN_PRIORITY);
  253.     while (aniThread == me) {
  254.         boolean animating = false;
  255.         for (int i = areas.length; --i >= 0; ) {
  256.         animating = areas[i].animate() || animating;
  257.         }
  258.         try {
  259.         synchronized(this) {
  260.             wait(animating ? 100 : 0);
  261.         }
  262.         } catch (InterruptedException e) {
  263.         break;
  264.         }
  265.     }
  266.     }
  267.  
  268.     public synchronized void startAnimation() {
  269.     notify();
  270.     }
  271.  
  272.     public synchronized void stop() {
  273.     aniThread = null;
  274.     notify();
  275.     for (int i = 0; i < areas.length; i++) {
  276.         areas[i].exit();
  277.     }
  278.     }
  279.  
  280.     /**
  281.      * Check the size of this applet while the image is being loaded.
  282.      */
  283.     void checkSize() {
  284.     int w = baseImage.getWidth(this);
  285.     int h = baseImage.getHeight(this);
  286.     if (w > 0 && h > 0) {
  287.         resize(w, h);
  288.         synchronized(this) {
  289.         fullrepaint = true;
  290.         }
  291.         repaint(0, 0, w, h);
  292.     }
  293.     }
  294.  
  295.     private boolean fullrepaint = false;
  296.     private final static long UPDATERATE = 100;
  297.  
  298.     /**
  299.      * Handle updates from images being loaded.
  300.      */
  301.     public boolean imageUpdate(Image img, int infoflags,
  302.                    int x, int y, int width, int height) {
  303.     if ((infoflags & (WIDTH | HEIGHT)) != 0) {
  304.         checkSize();
  305.     }
  306.     if ((infoflags & (SOMEBITS | FRAMEBITS | ALLBITS)) != 0) {
  307.         synchronized(this) {
  308.         fullrepaint = true;
  309.         }
  310.         repaint(((infoflags & (FRAMEBITS | ALLBITS)) != 0)
  311.             ? 0 : UPDATERATE,
  312.             x, y, width, height);
  313.     }
  314.     return (infoflags & (ALLBITS | ERROR)) == 0;
  315.     }
  316.  
  317.     /**
  318.      * Paint the image and all active highlights.
  319.      */
  320.     public void paint(Graphics g) {
  321.     synchronized(this) {
  322.         fullrepaint = false;
  323.     }
  324.     if (baseImage == null) {
  325.         return;
  326.     }
  327.     g.drawImage(baseImage, 0, 0, this);
  328.     if (areas != null) {
  329.         for (int i = areas.length; --i >= 0; ) {
  330.         areas[i].highlight(g);
  331.         }
  332.     }
  333.     }
  334.  
  335.     /**
  336.      * Update the active highlights on the image.
  337.      */
  338.     public void update(Graphics g) {
  339.     boolean full;
  340.     synchronized(this) {
  341.         full = fullrepaint;
  342.     }
  343.     if (full) {
  344.         paint(g);
  345.         return;
  346.     }
  347.     if (baseImage == null) {
  348.         return;
  349.     }
  350.     g.drawImage(baseImage, 0, 0, this);
  351.     if (areas == null) {
  352.         return;
  353.     }
  354.     // First unhighlight all of the deactivated areas
  355.     for (int i = areas.length; --i >= 0; ) {
  356.         areas[i].highlight(g);
  357.     }
  358.     }
  359.  
  360.     /**
  361.      * Make sure that no ImageAreas are highlighted.
  362.      */
  363.     public boolean mouseExit(java.awt.Event evt, int x, int y) {
  364.     for (int i = 0; i < areas.length; i++) {
  365.         areas[i].checkExit();
  366.     }
  367.  
  368.     return true;
  369.     }
  370.  
  371.     /**
  372.      * Find the ImageAreas that the mouse is in.
  373.      */
  374.     public boolean mouseMove(java.awt.Event evt, int x, int y) {
  375.     boolean eaten = false;
  376.  
  377.     for (int i = 0; i < areas.length; i++) {
  378.         if (!eaten && areas[i].inside(x, y)) {
  379.         eaten = areas[i].checkEnter(x, y);
  380.         } else {
  381.         areas[i].checkExit();
  382.         }
  383.     }
  384.  
  385.     return true;
  386.     }
  387.  
  388.     int pressX;
  389.     int pressY;
  390.  
  391.     /**
  392.      * Inform all active ImageAreas of a mouse press.
  393.      */
  394.     public boolean mouseDown(java.awt.Event evt, int x, int y) {
  395.     pressX = x;
  396.     pressY = y;
  397.  
  398.     for (int i = 0; i < areas.length; i++) {
  399.         if (areas[i].inside(x, y)) {
  400.         if (areas[i].press(x, y)) {
  401.             break;
  402.         }
  403.         }
  404.     }
  405.  
  406.     return true;
  407.     }
  408.  
  409.     /**
  410.      * Inform all active ImageAreas of a mouse release.
  411.      * Only those areas that were inside the original mouseDown()
  412.      * are informed of the mouseUp.
  413.      */
  414.     public boolean mouseUp(java.awt.Event evt, int x, int y) {
  415.     for (int i = 0; i < areas.length; i++) {
  416.         if (areas[i].inside(pressX, pressY)) {
  417.         if (areas[i].lift(x, y)) {
  418.             break;
  419.         }
  420.         }
  421.     }
  422.  
  423.     return true;
  424.     }
  425.  
  426.     /**
  427.      * Inform all active ImageAreas of a mouse drag.
  428.      * Only those areas that were inside the original mouseDown()
  429.      * are informed of the mouseUp.
  430.      */
  431.     public boolean mouseDrag(java.awt.Event evt, int x, int y) {
  432.     mouseMove(evt, x, y);
  433.     for (int i = 0; i < areas.length; i++) {
  434.         if (areas[i].inside(pressX, pressY)) {
  435.         if (areas[i].drag(x, y)) {
  436.             break;
  437.         }
  438.         }
  439.     }
  440.  
  441.     return true;
  442.     }
  443.  
  444.     /**
  445.      * Scan all areas looking for the topmost status string.
  446.      */
  447.     public void newStatus() {
  448.     String msg = null;
  449.     for (int i = 0; i < areas.length; i++) {
  450.         msg = areas[i].getStatus(msg);
  451.     }
  452.     showStatus(msg);
  453.     }
  454. }
  455.