/* (C) 2000-2002, DIUF, http://www.unifr.ch/diuf * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package iiuf.xmillum; import iiuf.dom.DOMUtils; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.util.Hashtable; import javax.swing.JComponent; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Displayable * * This class defines one specific displayable element. * * @author $Author: ohitz $ * @version $Revision: 1.1 $ */ public abstract class Displayable { /** All children */ public Displayable[] childs = new Displayable[0]; /** Bounding box */ public Rectangle bounds; /** Element which produced this object */ public Element element; /** * Constructs a Displayable. * * @param e Element bound to this displayable. */ public Displayable(Element e) { element = e; } /** * Searches the displayable that represents a given element. * * @param e Element whose Displayable we are looking for. * @return Displayable representing the given element. */ public Displayable getDisplayableForElement(Element e) { if (element == e) { return this; } for (int i = 0; i < childs.length; i++) { Displayable result = childs[i].getDisplayableForElement(e); if (result != null) { return result; } } return null; } /** * Paints the element. * * @param g Current graphics context. */ public final void paint(Graphics2D g, double scale) { Rectangle b = getBounds(scale); if (b.intersects(g.getClipBounds())) { paintObject(g, scale); if (appearance != null) { if (appearance.paint(g, scale)) { appearance = null; } } paintChildren(g, scale); } } private DisplayableAppearance appearance; public void setAppearance(DisplayableAppearance a) { appearance = a; } /** * Paints the object. Overridden by subclasses. * * @param g Current graphics context. */ public abstract void paintObject(Graphics2D g, double scale); /** * Paints the children of this object. * * @param g Current graphics context. */ public final void paintChildren(Graphics2D g, double scale) { for (int i = 0; i < childs.length; i++) { childs[i].paint(g, scale); } } /** * Returns the bounds of this object and all contained children. * * @return Bounding box. */ public Rectangle getBounds(double scale) { Rectangle b = null; for (int i = 0; i < childs.length; i++) { Rectangle r = childs[i].getBounds(scale); if (b == null) { b = new Rectangle(r); } else { enlargeBounds(r, b); } } bounds = b; return b; } /** * Enlarge one rectangle by another one. * * @param r1 Rectangle that enlarges the other one. * @param r2 Rectangle to be enlarged. */ private void enlargeBounds(Rectangle r1, Rectangle r2) { if (r1.x < r2.x) { r2.width += r2.x - r1.x; r2.x = r1.x; } if (r1.y < r2.y) { r2.height += r2.y - r1.y; r2.y = r1.y; } if (r1.x+r1.width > r2.x+r2.width) { r2.width = r1.x + r1.width - r2.x; } if (r1.y+r1.height > r2.y+r2.height) { r2.height = r1.y + r1.height - r2.y; } } /** * Checks if (x,y) is inside the bounds of this object. * * @param x horizontal coordinate * @param y vertical coordinate * @return true if (x, y) is within the bounds */ public boolean contains(int x, int y, double scale) { Rectangle b = getBounds(scale); return b.contains(x, y); } /** Get highlight color corresponding to another color. */ private static Hashtable hilightColors = new Hashtable(); protected Color getHilightColor(Color rgbColor) { Color h = (Color) hilightColors.get(rgbColor); if (h == null) { float[] rgb = rgbColor.getRGBColorComponents(null); float[] hsb = Color.RGBtoHSB((int) rgb[0], (int) rgb[1], (int) rgb[2], null); h = Color.getHSBColor(hsb[0]+0.5F, hsb[1], Math.max(1.0F, hsb[2]*2)); hilightColors.put(rgbColor, h); } return h; } /** Mouse Clicked */ public boolean mouseClicked(MouseEvent event, double scale) { return mouseClickedRecursive(event, scale); } protected boolean mouseClickedRecursive(MouseEvent event, double scale) { for (int i = 0; i < childs.length; i++) { if (childs[i].contains(event.getX(), event.getY(), scale)) { //System.out.println("mouse clicked recursive in level " + i); if (childs[i].mouseClicked(event, scale)) return true; } } return mouseClickedAction(event); } protected boolean mouseClickedAction(MouseEvent event) { return false; } /** Mouse Pressed */ public boolean mousePressed(MouseEvent event, double scale) { return mousePressedRecursive(event, scale); } protected boolean mousePressedRecursive(MouseEvent event, double scale) { for (int i = 0; i < childs.length; i++) { if (childs[i].contains(event.getX(), event.getY(), scale)) { //System.out.println("mouse pressed recursive in level " + i); if (childs[i].mousePressed(event, scale)) return true; } } return mousePressedAction(event); } protected boolean mousePressedAction(MouseEvent event) { return false; } /** Mouse Released */ public boolean mouseReleased(MouseEvent event, double scale) { return mouseReleasedRecursive(event, scale); } protected boolean mouseReleasedRecursive(MouseEvent event, double scale) { for (int i = 0; i < childs.length; i++) { if (childs[i].contains(event.getX(), event.getY(), scale)) { if (childs[i].mouseReleased(event, scale)) return true; } } return mouseReleasedAction(event); } protected boolean mouseReleasedAction(MouseEvent event) { return false; } /** Mouse Dragged */ public boolean mouseDragged(MouseEvent event, double scale) { return mouseDraggedRecursive(event, scale); } protected boolean mouseDraggedRecursive(MouseEvent event, double scale) { for (int i = 0; i < childs.length; i++) { if (childs[i].contains(event.getX(), event.getY(), scale)) { if (childs[i].mouseDragged(event, scale)) return true; } } return mouseDraggedAction(event); } protected boolean mouseDraggedAction(MouseEvent event) { return false; } /** Mouse Moved */ public boolean mouseMoved(MouseEvent event, double scale) { return mouseMovedRecursive(event, scale); } protected boolean mouseMovedRecursive(MouseEvent event, double scale) { for (int i = 0; i < childs.length; i++) { if (childs[i].contains(event.getX(), event.getY(), scale)) { if (childs[i].mouseMoved(event, scale)) return true; } } return mouseMovedAction(event); } protected boolean mouseMovedAction(MouseEvent event) { return false; } }