import java.awt.*; import java.net.*; /** A class that supports Images as Components that can be repositioned * with the mouse. As with all Components, the effects may be eventually * undone by the layoutManager if it is not off (null) or chosen * appropriately. *

* By default, with FlowLayout the Icon takes its minimum size * (just enclosing the image). The default with BorderLayout is * to expand to fill the region in width (North/South), height * (East/West) or both (Center). This is the same behavior as the builtin * Label class and of ImageLabel, upon which Icon is built. If you perform * an explicit resize or * reshape call before adding the ImageLabel to the * Container, this size will override the defaults. *

* This can be used in two ways. In the first, the Component itself * watches the mouse events, and allows the user to drag it around. * This has one major advantage: *

* * However, given the current state of the AWT, it has two main disadvantages: * * * On the other hand, you can have the Container insert a small amount of code * into its handleEvent method. This has two advantages: * * * This has two disadvantages: * * * Resolving these pros/cons depends upon the application, so the Icon class * can be used either way. If the ignoreEvents variable is set to true * (the default), then it cannot be dragged without adding code to the * Container. *

* If the Container does not already have a custom handleEvent method, * insert the following: *

*

 *    public boolean handleEvent(Event event) {
 *      if (Icon.handleIconEvent(event, this))
 *        return(true);
 *      else
 *        return(super.handleEvent(event));
 *    }
 *  
* If the Container does already have a custom handleEvent method, modify it * by adding the Icon.handleEvent test at the top, as illustrated * below: *

*

 *    public boolean handleEvent(Event event) {
 *      if (Icon.handleIconEvent(event, this))
 *        return(true);
 *      Original handleEvent code here
 *    }
 *  
* If instead you want the Icon to handle its own mouse events, simply * set the Icon's ignoreEvents variable to false. Do not mix these * two modes in a single program. *

* The original of the Icon source code is at * * http://www.apl.jhu.edu/~hall/java/ImageLabel/Icon.java, * the documentation is at * * .../Icon.html, and a small example program can be found at * * .../IconTest.html. *

* No warranty of any kind is provided. * Permission is granted to use and/or modify * for any purpose. *

* 7/96 Marty Hall: *

* * @version 1.0 (August 1996) * @see ImageButton */ public class Icon extends ImageLabel { //------------------------------------------------------------------------- /** Should the image be highlighted when you click/drag? Default = true. */ public boolean highlightable = true; /** How thick should the highlighting rectangle be? * Default = 3. Ignored if highlightable is false. */ public int highlightThickness = 3; /** The Color to use for the highlight rectangle. * Default is Color.blue. Ignored if highlightable is false. */ public Color highlightColor = Color.blue; /** Can the image be dragged with the mouse? * Default = true. (If it will always be false, use * an ImageLabel instead). */ public boolean draggable = true; // Is it currently being dragged? This is used in the case when // the Container is tracking movement, since the mouse may not // be over the Component. private boolean beingDragged = false; /** The cursor to get when dragging. Default is Frame.MOVE_CURSOR */ public int dragCursor = Frame.MOVE_CURSOR; // The previous cursor, so that it can be changed back private int previousCursor = Frame.DEFAULT_CURSOR; // The Frame that owns the cursor private Frame topFrame = null; // TO DO: Document private boolean ignoreEvents = true; //------------------------------------------------------------------------- /** If the Container was always going to handle the mouse events, * it could simply look up the event type and call a helper method * directly. This, however, allows event handling either locally * (if ignoreEvents is false) or in the Container. * You cannot override this arbitrarily in subclasses. */ public boolean handleEvent(Event event) { if (ignoreEvents) { return(false); } else { return(super.handleEvent(event)); } } //------------------------------------------------------------------------- /** Called from the handleEvent method of the Container if the Container * is to handle the mouse events. See the introduction to this class. */ public static boolean handleIconEvent(Event event, Container container) { int x = event.x; int y = event.y; Icon targetIcon = iconBeingDragged(container); if (targetIcon == null) { // You should be able to use container.locate instead of // Icon.componentUnder(x, y, container), but Netscape // has a bug with locate() and inside(). They work fine // in applications and appletviewer. Component targetComponent = Icon.componentUnder(x, y, container); // Component targetComponent = container.locate(x, y); if (!(targetComponent instanceof Icon)) return(false); else targetIcon = (Icon)targetComponent; } Point iconLocation = targetIcon.location(); int iconX = iconLocation.x; int iconY = iconLocation.y; event.translate(-iconX, -iconY); targetIcon.ignoreEvents = false; boolean result = targetIcon.handleEvent(event); targetIcon.ignoreEvents = true; event.translate(iconX, iconY); return(result); } //------------------------------------------------------------------------- private static Icon iconBeingDragged(Container container) { Component[] components = container.getComponents(); Component current; for(int i=0; i= x) && ((componentSize.height + componentLocation.y) >= y)) return(component); } return(null); } //------------------------------------------------------------------------- // Ignored if the debug variable is false. private void report(String eventType, int x, int y) { debug("mouse" + eventType + " at (" + x + "," + y + ")."); } //------------------------------------------------------------------------- // Used for setting the cursor. private Frame parentFrame() { if (topFrame != null) return(topFrame); else { Container parent = getParent(); while (parent != null) { if (parent instanceof Frame) { topFrame = ((Frame)parent); return(topFrame); } else parent = parent.getParent(); } System.out.println("[parentFrame] parent is null."); return(null); } } //------------------------------------------------------------------------- }