home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 22.5 KB | 823 lines |
- /*---------------------------------------------------------------------------
-
- Written by the Personal Journal developers of Dow Jones & Company, Inc.
-
- Dow Jones makes no representations or warranties about
- the suitability of this software, either express or
- implied, including but not limited to the implied warranties
- of merchantability, fitness for a particular purpose,
- or non-infringement. Dow Jones will not be liable for
- any damages suffered by a user as a result of using,
- modifying or distributing this software or its derivatives.
-
-
- @(#)WeatherImageMap.java 0.00 23-Jan-96
-
- A WeatherImageMap that extends Canvas.
- Most of the code here was borrowed and modified from Java demo(ImageMap).
- This file contains three classes: WeatherImageMap, NameArea, and HighlightFilter.
-
- Authors:
-
- jlee James Lee
-
-
- Version Ident:
-
- $Header$
-
-
- History:
-
- 0.00 23-Jan-96 jlee Initial Creation
- 14-Feb-96 jlee Corrected a mapping bug: mapping between region and weather report
- 19-Mar-96 jlee Added weather region message functionality
-
- ---------------------------------------------------------------------------*/
-
- package pj.awt;
-
-
- import pj.awt.PjTabNotebook;
-
-
-
-
-
-
- import java.awt.Canvas;
- import java.awt.Event;
- import java.awt.Graphics;
- import java.awt.image.*;
- import java.awt.Image;
- import java.awt.Rectangle;
- import java.net.URL;
- import java.util.StringTokenizer;
- import java.util.Vector;
- import java.util.Hashtable;
-
-
- import java.util.*;
-
-
- /**
- * An extensible WeatherImageMap Canvas class.
- * The active areas on the image are controlled by ImageMapArea classes
- * which are hard-coded in WeatherImageMap class.
- *
- * @author James Lee
- * @version 0.00 23-Jan-96
- */
- public class WeatherImageMap extends Canvas
- {
- // --- Class variables
-
- /**
- * The primary highlight mode to be used.
- */
- static final int BRIGHTER = 0;
- static final int DARKER = 1;
-
-
-
- // --- Instance variables
-
- /**
- * The unhighlighted image being mapped.
- */
- Image baseImage;
-
- /**
- * The list of image area handling objects;
- */
- ImageMapArea areas[];
-
- /**
- * The primary highlight mode to be used.
- */
- int hlmode = DARKER;
-
- /**
- * The percentage of highlight to apply for the primary highlight mode.
- */
- int hlpercent = 25;
-
- /**
- * The string array of rectangular area in the weather map.
- */
- private String strRec[];
-
-
- private boolean fullrepaint = false;
- private Rectangle repaintrect = new Rectangle();
- private long lastupdate = 0;
- private final static long UPDATERATE = 100;
-
- private int pressX;
- private int pressY;
-
-
- // --- Public operations
-
-
- /**
- * 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)
- {
- Image cropped = makeImage(baseImage, new CropImageFilter(x, y, w, h));
- return makeImage(cropped, filter);
- }
-
- /**
- * Make the primary highlighted version of the baseImage.
- */
- Image makeImage(Image orig, ImageFilter filter)
- {
- return createImage(new FilteredImageSource(orig.getSource(), filter));
- }
-
- /**
- * public WeatherImageMap constructer and initialize the ImageMapAreas.
- *
- * @param img An image(weather map)
- */
- public WeatherImageMap(Image img)
- {
- baseImage = img;
-
- strRec = new String[10];
- strRec[0] = "87,51, 27,30, U.S. Northeast";
- strRec[1] = "62,64, 24,28, U.S. Middle";
- strRec[2] = "78,80, 19,23, U.S. Southeast";
- strRec[3] = "38,36, 56,33, Canada";
- strRec[4] = "41,68, 26,31, U.S. West";
- strRec[5] = "137,47, 33,36, Europe";
- strRec[6] = "86,101, 44,56, South America/Caribbean";
- strRec[7] = "167,75, 29,29, Middle East";
- strRec[8] = "196,49, 75,103, Asia/Australia";
- strRec[9] = "138,84, 36,52, Africa";
-
- Vector areaVec = new Vector();
- for( int i = 0; i < 10; i++ )
- {
- ImageMapArea newArea;
- newArea = new NameArea();
- newArea.init(this, strRec[i]);
- areaVec.addElement(newArea);
- }
- areas = new ImageMapArea[areaVec.size()];
- areaVec.copyInto(areas);
-
- //Checking image size asynchronously.
- checkSize();
- System.out.println("Debug-WeatherImageMap:constructed");
- }
-
- /**
- * Check the size of this Canvas while the image is being loaded.
- */
- synchronized void checkSize()
- {
- int w = baseImage.getWidth(this);
- int h = baseImage.getHeight(this);
-
- if (w > 0 && h > 0)
- {
- resize(w, h);
- repaintrect.x = repaintrect.y = 0;
- repaintrect.width = w;
- repaintrect.height = h;
- fullrepaint = true;
- repaint();
- }
- }
-
-
-
- /**
- * Handle updates from images being loaded.
- *
- * @param img An Image
- * @param infoflags Image info flags
- * @param x X coordinate of the Image
- * @param y Y coordinate of the Image
- * @param width Width of the Image
- * @param height Height of the Image
- *
- * @return true if image has been changed, false otherwise.
- */
- 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)
- {
- repaint(((infoflags & (FRAMEBITS | ALLBITS)) != 0) ? 0 : UPDATERATE, x, y, width, height);
- }
- return (infoflags & (ALLBITS | ERROR)) == 0;
- }
-
- /**
- * Paint the image and all active highlights.
- *
- * @param g An Graphics object
- */
- public void paint(Graphics g)
- {
- synchronized(this)
- {
- if (fullrepaint)
- {
- g = g.create();
- g.clipRect(repaintrect.x, repaintrect.y, repaintrect.width, repaintrect.height);
- fullrepaint = false;
- }
- }
-
- if (baseImage == null)
- {
- return;
- }
-
- g.drawImage(baseImage, 0, 0, this);
-
- if (areas != null)
- {
- for (int i = areas.length; --i >= 0; )
- {
- if (areas[i].active || areas[i].entered)
- {
- areas[i].setState(g, areas[i].entered);
- }
- }
- }
- }
-
- /**
- * Update the active highlights on the image.
- *
- * @param g An Graphics object
- */
- public void update(Graphics g)
- {
- if (fullrepaint)
- {
- 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; )
- {
- if (areas[i].active && !areas[i].entered)
- {
- areas[i].setState(g, false);
- }
- }
-
- // Then highlight all of the activated areas
- for (int i = areas.length; --i >= 0; )
- {
- if (areas[i].entered)
- {
- areas[i].setState(g, true);
- }
- }
- }
-
- /**
- * Make sure that no ImageMapAreas are highlighted.
- */
- public void mouseExit()
- {
- boolean changed = false;
-
- for (int i = 0; i < areas.length; i++)
- {
- if (areas[i].active)
- {
- areas[i].entered = false;
- changed = true;
- }
- }
-
- if (changed)
- {
- repaint();
- }
- }
-
- /**
- * Find the ImageMapAreas that the mouse is in.
- */
- public boolean mouseMove(java.awt.Event evt, int x, int y)
- {
- boolean changed = false;
- boolean propagate = true;
-
- for (int i = 0; i < areas.length; i++)
- {
- if (areas[i].inside(x, y))
- {
- areas[i].entered = propagate;
- if (areas[i].terminal)
- {
- propagate = false;
- }
- }
- else
- {
- areas[i].entered = false;
- }
-
- if (areas[i].active != areas[i].entered)
- {
- changed = true;
- }
- }//for
-
- if (changed)
- {
- repaint();
- }
-
- return true;
- }//mouseMove
-
-
-
- /**
- * Inform all active ImageMapAreas of a mouse press.
- *
- * @param evt An Event object
- * @param x X coordinate of mouse button press
- * @param y Y coordinate of mouse button press
- */
- public boolean mouseDown(java.awt.Event evt, int x, int y)
- {
- pressX = x;
- pressY = y;
- Event newEvent;
-
- for (int i = 0; i < areas.length; i++)
- {
- if (areas[i].inside(x, y))
- {
- areas[i].press(x, y);
- if (areas[i].terminal)
- {
- newEvent = new Event( this, Event.ACTION_EVENT, ((NameArea)areas[i]).name );
- postEvent( newEvent );
-
- break;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Inform all active ImageMapAreas of a mouse release.
- * Only those areas that were inside the original mouseDown()
- * are informed of the mouseUp.
- *
- * @param evt An Event object
- * @param x X coordinate of mouse release
- * @param y Y coordinate of mouse release
- */
- 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))
- {
- areas[i].lift(x, y);
- if (areas[i].terminal)
- {
- break;
- }
- }
- }
- mouseExit();
- return true;
- }
-
- /**
- * Inform all active ImageMapAreas of a mouse drag.
- * Only those areas that were inside the original mouseDown()
- * are informed of the mouseUp.
- *
- * @param evt An Event object
- * @param x X coordinate of mouse drag
- * @param y Y coordinate of mouse drag
- */
- 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))
- {
- areas[i].drag(x, y);
- if (areas[i].terminal)
- {
- break;
- }
- }
- }
-
- return true;
- }
- }//class WeatherImageMap
-
- /**
- * The base ImageMapArea class.
- * This class performs the basic functions that most sub-classed ImageMapArea
- * classes will need and delegates specific actions to the subclasses.
- *
- * @author Jim Graham, modified by James Lee
- * @version 0.00 23-Jan-96
- */
- class ImageMapArea implements ImageObserver
- {
- // --- Instance variables
-
- /** The applet parent that contains this ImageMapArea. */
- WeatherImageMap parent;
-
- /** The X location of the area (if rectangular). */
- int X;
-
- /** The Y location of the area (if rectangular). */
- int Y;
-
- /** The size().width of the area (if rectangular). */
- int W;
-
- /** The size().height of the area (if rectangular). */
- int H;
-
- /**
- * This flag indicates whether the user was in this area during the
- * last scan of mouse locations.
- */
- boolean entered = false;
-
- /** This flag indicates whether the area is currently highlighted. */
- boolean active = false;
-
- /**
- * This flag indicates whether the area is terminal. Terminal areas
- * prevent any areas which are under them from being activated when
- * the mouse is inside them. Some areas may wish to change this to
- * false so that they can augment other areas that they are on top of.
- */
- boolean terminal = true;
-
- /**
- * This is the default highlight image if no special effects are
- * needed to draw the highlighted image. It is created by the
- * default "makeImages()" method.
- */
- Image hlImage;
-
- // --- Public operations
- /**
- * Initialize this ImageMapArea as called from the Canvas.
- * If the subclass does not override this initializer, then it
- * will perform the basic functions of setting the parent Canvas
- * and parsing out 4 numbers from the argument string which specify
- * a rectangular region for the ImageMapArea to act on.
- * The remainder of the argument string is passed to the handleArg()
- * method for more specific handling by the subclass.
- */
- public void init(WeatherImageMap parent, String args)
- {
- this.parent = parent;
-
- StringTokenizer st = new StringTokenizer(args, ", ");
- X = Integer.parseInt(st.nextToken());
- Y = Integer.parseInt(st.nextToken());
- W = Integer.parseInt(st.nextToken());
- H = Integer.parseInt(st.nextToken());
-
- if (st.hasMoreTokens())
- {
- // hasMoreTokens() Skips the trailing comma
- handleArg(st.nextToken(""));
- }
- else
- {
- handleArg(null);
- }
-
- makeImages();
- }
-
- /**
- * This method handles the remainder of the argument string after
- * the standard initializer has parsed off the 4 rectangular
- * parameters. If the subclass does not override this method,
- * the remainder will be ignored.
- *
- * @param s The remainer of region argument string
- */
- public void handleArg(String s)
- {
- }
-
- /**
- * This method sets the image to be used to render the ImageMapArea
- * when it is highlighted.
- *
- * @param img A rendering image
- */
- public void setHighlight(Image img)
- {
- hlImage = img;
- }
-
- /**
- * This method handles the construction of the various images
- * used to highlight this particular ImageMapArea when the user
- * interacts with it.
- */
- public void makeImages()
- {
- setHighlight(parent.getHighlight(X, Y, W, H));
- }
-
- /**
- * This method tests to see if a point is inside this ImageMapArea.
- * The standard method assumes a rectangular area as parsed by
- * the standard initializer. If a more complex area is required
- * then this method will have to be overridden by the subclass.
- */
- public boolean inside(int x, int y)
- {
- return (x >= X && x < (X + W) && y >= Y && y < (Y + H));
- }
-
- /**
- * This utility method draws a rectangular subset of a highlight
- * image.
- */
- public void drawImage(Graphics g, Image img, int imgx, int imgy, int x, int y, int w, int h)
- {
- Graphics ng = g.create();
- ng.clipRect(x, y, w, h);
- ng.drawImage(img, imgx, imgy, this);
- ng.finalize();
- }
-
- /**
- * This method handles the updates from drawing the images.
- */
- public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
- {
- if (img == hlImage)
- {
- return parent.imageUpdate(img, infoflags, x + X, y + Y, width, height);
- }
- else
- {
- return false;
- }
- }
-
- /**
- * This utility method shows a string in the status bar.
- */
- public void showStatus(String msg)
- {
- //parent.getAppletContext().showStatus(msg);
- PjTabNotebook.getStatusBar().setMessage( msg );
- }
-
- /**
- * This method highlights the specified area when the user enters
- * it with his mouse. The standard highlight method is to replace
- * the indicated rectangular area of the image with the primary
- * highlighted image.
- */
- public void highlight(Graphics g, boolean on)
- {
- if (on)
- {
- g.drawImage(hlImage, X, Y, this);
- }
- else
- {
- drawImage(g, parent.baseImage, 0, 0, X, Y, W, H);
- }
- }
-
- /**
- * This method changes the active state of the ImageMapArea, which
- * indicates whether the user is currently "inside" this area.
- * It turns around and calls the highlight method which is likely
- * to have been overridden by subclasses seeking a custom highlight.
- */
- public void setState(Graphics g, boolean on)
- {
- highlight(g, on);
- active = on;
- }
-
- /**
- * The press method is called when the user presses the mouse
- * button inside the ImageMapArea. The location is supplied, but
- * the standard implementation is to call the overloaded method
- * with no arguments.
- */
- public void press(int x, int y)
- {
- press();
- }
-
- /**
- * The overloaded press method is called when the user presses the
- * mouse button inside the ImageMapArea. This method can be overridden
- * if the ImageMapArea does not need to know the location of the press.
- */
- public void press()
- {
- }
-
- /**
- * The lift method is called when the user releases the mouse button.
- * The location is supplied, but the standard implementation is to
- * call the overloaded method with no arguments. Only those ImageMapAreas
- * that were informed of a press will be informed of the corresponding
- * release.
- */
- public void lift(int x, int y)
- {
- lift();
- }
-
- /**
- * The overloaded lift method is called when the user releases the
- * mouse button. This method can be overridden if the ImageMapArea
- * does not need to know the location of the release.
- */
- public void lift()
- {
- }
-
- /**
- * The drag method is called when the user moves the mouse while
- * the button is pressed. Only those ImageMapAreas that were informed
- * of a press will be informed of the corresponding mouse movements.
- */
- public void drag(int x, int y)
- {
- }
- }
-
- /**
- * A message feedback ImageMapArea class.
- * This class extends the basic ImageMapArea Class to show the a given
- * message in the status message area when the user enters this area.
- *
- * @author Jim Graham, modified by James Lee
- * @version 0.00 23-Jan-96
- */
- class NameArea extends ImageMapArea
- {
-
- // --- Instance variables
-
- /** The string to be shown in the status message area. */
- String name;
-
- /**
- * The argument is the string to be displayed in the status message
- * area. This method also sets this type of area to be non-terminal.
- */
- public void handleArg(String arg)
- {
- name = arg;
- }
-
- /**
- * The highlight method displays the message in addition to the usual
- * graphical highlight feedback.
- */
- public void highlight(Graphics g, boolean on)
- {
- super.highlight(g, on);
- showStatus(on ? name + ": Click the region to view weather" : null);
- }
-
- /**
- * The overloaded press method is called when the user presses the
- * mouse button inside the ImageMapArea. This method can be overridden
- * if the ImageMapArea does not need to know the location of the press.
- */
- public void press()
- {
- }
- }
-
- /**
- * This class extends the basic RGBImageFilter Class to brighten or darken
- * the rectangular area.
- *
- * @author James Lee
- * @version 0.00 23-Jan-96
- */
- class HighlightFilter extends RGBImageFilter
- {
-
- // --- Instance variables
- boolean brighter;
- int percent;
-
- public HighlightFilter(boolean b, int p)
- {
- brighter = b;
- percent = p;
- canFilterIndexColorModel = true;
- }
-
- /**
- * Implements the abstract method in RGBImageFilter.
- * Converts a single input pixel to a single output pixel brightened or darkened.
- */
- public int filterRGB(int x, int y, int rgb)
- {
- int r = (rgb >> 16) & 0xff;
- int g = (rgb >> 8) & 0xff;
- int b = (rgb >> 0) & 0xff;
-
- if (brighter)
- {
- r = (255 - ((255 - r) * (100 - percent) / 100));
- g = (255 - ((255 - g) * (100 - percent) / 100));
- b = (255 - ((255 - b) * (100 - percent) / 100));
- }
- else
- {
- r = (r * (100 - percent) / 100);
- g = (g * (100 - percent) / 100);
- b = (b * (100 - percent) / 100);
- }
-
- if (r < 0)
- r = 0;
-
- if (r > 255)
- r = 255;
-
- if (g < 0)
- g = 0;
-
- if (g > 255)
- g = 255;
-
- if (b < 0)
- b = 0;
-
- if (b > 255)
- b = 255;
-
- return (rgb & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
- }
- }
-
-
-