home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 November
/
Chip_1998-11_cd.bin
/
tema
/
Cafe
/
VCSAMPL.BIN
/
ImageMap.java
< prev
next >
Wrap
Text File
|
1996-12-06
|
12KB
|
454 lines
/*
* @(#)ImageMap.java 1.8 96/12/06
*
* Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import java.applet.Applet;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.MediaTracker;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Hashtable;
import java.net.URL;
import java.awt.image.ImageProducer;
import java.awt.image.ImageFilter;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.net.MalformedURLException;
/**
* An extensible ImageMap applet class.
* The active areas on the image are controlled by ImageArea classes
* that can be dynamically loaded over the net.
*
* @author Jim Graham
* @version 1.8, 12/06/96
*/
public class ImageMap extends Applet implements Runnable {
/**
* The unhighlighted image being mapped.
*/
Image baseImage;
/**
* The list of image area handling objects;
*/
ImageMapArea areas[];
/**
* The primary highlight mode to be used.
*/
static final int BRIGHTER = 0;
static final int DARKER = 1;
int hlmode = BRIGHTER;
/**
* The percentage of highlight to apply for the primary highlight mode.
*/
int hlpercent = 50;
/**
* The MediaTracker for loading and constructing the various images.
*/
MediaTracker tracker;
/**
* Get a rectangular region of the baseImage highlighted according to
* the primary highlight specification.
*/
Image getHighlight(int x, int y, int w, int h) {
return getHighlight(x, y, w, h, hlmode, hlpercent);
}
/**
* Get a rectangular region of the baseImage with a specific highlight.
*/
Image getHighlight(int x, int y, int w, int h, int mode, int percent) {
return getHighlight(x, y, w, h, new HighlightFilter(mode == BRIGHTER,
percent));
}
/**
* Get a rectangular region of the baseImage modified by an image filter.
*/
Image getHighlight(int x, int y, int w, int h, ImageFilter filter) {
ImageFilter cropfilter = new CropImageFilter(x, y, w, h);
ImageProducer prod = new FilteredImageSource(baseImage.getSource(),
cropfilter);
return makeImage(prod, filter, 0);
}
/**
* Make a filtered image based on another image.
*/
Image makeImage(Image orig, ImageFilter filter) {
return makeImage(orig.getSource(), filter);
}
/**
* Make a filtered image based on another ImageProducer.
*/
Image makeImage(ImageProducer prod, ImageFilter filter) {
return makeImage(prod, filter,
(prod == baseImage.getSource()) ? 1 : 0);
}
/**
* Make a filtered image based on another ImageProducer.
* Add it to the media tracker using the indicated ID.
*/
Image makeImage(ImageProducer prod, ImageFilter filter, int ID) {
Image filtered = createImage(new FilteredImageSource(prod, filter));
tracker.addImage(filtered, ID);
return filtered;
}
/**
* Add an image to the list of images to be tracked.
*/
void addImage(Image img) {
tracker.addImage(img, 1);
}
/**
* Parse a string representing the desired highlight to be applied.
*/
void parseHighlight(String s) {
if (s == null) {
return;
}
if (s.startsWith("brighter")) {
hlmode = BRIGHTER;
if (s.length() > "brighter".length()) {
hlpercent = Integer.parseInt(s.substring("brighter".length()));
}
} else if (s.startsWith("darker")) {
hlmode = DARKER;
if (s.length() > "darker".length()) {
hlpercent = Integer.parseInt(s.substring("darker".length()));
}
}
}
/**
* Initialize the applet. Get attributes.
*
* Initialize the ImageAreas.
* Each ImageArea is a subclass of the class ImageArea, and is
* specified with an attribute of the form:
* areaN=ImageAreaClassName,arguments...
* The ImageAreaClassName is parsed off and a new instance of that
* class is created. The initializer for that class is passed a
* reference to the applet and the remainder of the attribute
* string, from which the class should retrieve any information it
* needs about the area it controls and the actions it needs to
* take within that area.
*/
public void init() {
String s;
tracker = new MediaTracker(this);
parseHighlight(getParameter("highlight"));
introTune = getParameter("startsound");
baseImage = getImage(getDocumentBase(), getParameter("img"));
Vector areaVec = new Vector();
int num = 1;
while (true) {
ImageMapArea newArea;
s = getParameter("area"+num);
if (s == null) {
// Try rect for backwards compatibility.
s = getParameter("rect"+num);
if (s == null) {
break;
}
try {
newArea = new HighlightArea();
newArea.init(this, s);
areaVec.addElement(newArea);
String url = getParameter("href"+num);
if (url != null) {
s += "," + url;
newArea = new LinkArea();
newArea.init(this, s);
areaVec.addElement(newArea);
}
} catch (Exception e) {
System.out.println("error processing: "+s);
e.printStackTrace();
break;
}
} else {
try {
int classend = s.indexOf(",");
String name = s.substring(0, classend);
newArea = (ImageMapArea) Class.forName(name).newInstance();
s = s.substring(classend+1);
newArea.init(this, s);
areaVec.addElement(newArea);
} catch (Exception e) {
System.out.println("error processing: "+s);
e.printStackTrace();
break;
}
}
num++;
}
areas = new ImageMapArea[areaVec.size()];
areaVec.copyInto(areas);
checkSize();
}
Thread aniThread = null;
String introTune = null;
public void start() {
if (introTune != null)
try {
play(new URL(getDocumentBase(), introTune));
} catch (MalformedURLException e) {}
if (aniThread == null) {
aniThread = new Thread(this);
aniThread.setName("ImageMap Animator");
aniThread.start();
}
}
public void run() {
Thread me = Thread.currentThread();
tracker.checkAll(true);
for (int i = areas.length; --i >= 0; ) {
areas[i].getMedia();
}
me.setPriority(Thread.MIN_PRIORITY);
while (aniThread == me) {
boolean animating = false;
for (int i = areas.length; --i >= 0; ) {
animating = areas[i].animate() || animating;
}
try {
synchronized(this) {
wait(animating ? 100 : 0);
}
} catch (InterruptedException e) {
break;
}
}
}
public synchronized void startAnimation() {
notify();
}
public synchronized void stop() {
aniThread = null;
notify();
for (int i = 0; i < areas.length; i++) {
areas[i].exit();
}
}
/**
* Check the size of this applet while the image is being loaded.
*/
void checkSize() {
int w = baseImage.getWidth(this);
int h = baseImage.getHeight(this);
if (w > 0 && h > 0) {
resize(w, h);
synchronized(this) {
fullrepaint = true;
}
repaint(0, 0, w, h);
}
}
private boolean fullrepaint = false;
private final static long UPDATERATE = 100;
/**
* Handle updates from images being loaded.
*/
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int width, int height) {
if ((infoflags & (WIDTH | HEIGHT)) != 0) {
checkSize();
}
if ((infoflags & (SOMEBITS | FRAMEBITS | ALLBITS)) != 0) {
synchronized(this) {
fullrepaint = true;
}
repaint(((infoflags & (FRAMEBITS | ALLBITS)) != 0)
? 0 : UPDATERATE,
x, y, width, height);
}
return (infoflags & (ALLBITS | ERROR)) == 0;
}
/**
* Paint the image and all active highlights.
*/
public void paint(Graphics g) {
synchronized(this) {
fullrepaint = false;
}
if (baseImage == null) {
return;
}
g.drawImage(baseImage, 0, 0, this);
if (areas != null) {
for (int i = areas.length; --i >= 0; ) {
areas[i].highlight(g);
}
}
}
/**
* Update the active highlights on the image.
*/
public void update(Graphics g) {
boolean full;
synchronized(this) {
full = fullrepaint;
}
if (full) {
paint(g);
return;
}
if (baseImage == null) {
return;
}
g.drawImage(baseImage, 0, 0, this);
if (areas == null) {
return;
}
// First unhighlight all of the deactivated areas
for (int i = areas.length; --i >= 0; ) {
areas[i].highlight(g);
}
}
/**
* Make sure that no ImageAreas are highlighted.
*/
public boolean mouseExit(java.awt.Event evt, int x, int y) {
for (int i = 0; i < areas.length; i++) {
areas[i].checkExit();
}
return true;
}
/**
* Find the ImageAreas that the mouse is in.
*/
public boolean mouseMove(java.awt.Event evt, int x, int y) {
boolean eaten = false;
for (int i = 0; i < areas.length; i++) {
if (!eaten && areas[i].inside(x, y)) {
eaten = areas[i].checkEnter(x, y);
} else {
areas[i].checkExit();
}
}
return true;
}
int pressX;
int pressY;
/**
* Inform all active ImageAreas of a mouse press.
*/
public boolean mouseDown(java.awt.Event evt, int x, int y) {
pressX = x;
pressY = y;
for (int i = 0; i < areas.length; i++) {
if (areas[i].inside(x, y)) {
if (areas[i].press(x, y)) {
break;
}
}
}
return true;
}
/**
* Inform all active ImageAreas of a mouse release.
* Only those areas that were inside the original mouseDown()
* are informed of the mouseUp.
*/
public boolean mouseUp(java.awt.Event evt, int x, int y) {
for (int i = 0; i < areas.length; i++) {
if (areas[i].inside(pressX, pressY)) {
if (areas[i].lift(x, y)) {
break;
}
}
}
return true;
}
/**
* Inform all active ImageAreas of a mouse drag.
* Only those areas that were inside the original mouseDown()
* are informed of the mouseUp.
*/
public boolean mouseDrag(java.awt.Event evt, int x, int y) {
mouseMove(evt, x, y);
for (int i = 0; i < areas.length; i++) {
if (areas[i].inside(pressX, pressY)) {
if (areas[i].drag(x, y)) {
break;
}
}
}
return true;
}
/**
* Scan all areas looking for the topmost status string.
*/
public void newStatus() {
String msg = null;
for (int i = 0; i < areas.length; i++) {
msg = areas[i].getStatus(msg);
}
showStatus(msg);
}
}