/* Violet - A program for editing UML diagrams. Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) 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 com.horstmann.violet.framework; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.Point2D; import java.beans.DefaultPersistenceDelegate; import java.beans.Encoder; import java.beans.Statement; import java.util.ArrayList; import java.util.List; /** A class that supplies convenience implementations for a number of methods in the Node interface */ public abstract class AbstractNode implements Node { /** Constructs a node with no parents or children. */ public AbstractNode() { children = new ArrayList(); parentNode = null; } public Object clone() { try { AbstractNode cloned = (AbstractNode)super.clone(); cloned.children = new ArrayList(children.size()); for (int i = 0; i < children.size(); i++) { Node n = (Node)children.get(i); cloned.children.set(i, n.clone()); n.setParent(cloned); } return cloned; } catch (CloneNotSupportedException exception) { return null; } } public void translate(double dx, double dy) { for (int i = 0; i < children.size(); i++) { Node n = (Node)children.get(i); n.translate(dx, dy); } } public boolean addEdge(Edge e, Point2D p1, Point2D p2) { return e.getEnd() != null; } public void removeEdge(Graph g, Edge e) { } public void removeNode(Graph g, Node e) { if (e == parentNode) parentNode = null; if (e.getParent() == this) children.remove(e); } public void layout(Graph g, Graphics2D g2, Grid grid) { } public boolean addNode(Node n, Point2D p) { return false; } public Node getParent() { return parentNode; } public void setParent(Node node) { parentNode = node; } public List getChildren() { return children; } public void addChild(int index, Node node) { Node oldParent = node.getParent(); if (oldParent != null) oldParent.removeChild(node); children.add(index, node); node.setParent(this); } public void addChild(Node node) { addChild(children.size(), node); } public void removeChild(Node node) { if (node.getParent() != this) return; children.remove(node); node.setParent(null); } public void draw(Graphics2D g2) { Shape shape = getShape(); if (shape == null) return; /* Area shadow = new Area(shape); shadow.transform(AffineTransform.getTranslateInstance(SHADOW_GAP, SHADOW_GAP)); shadow.subtract(new Area(shape)); */ Color oldColor = g2.getColor(); g2.translate(SHADOW_GAP, SHADOW_GAP); g2.setColor(SHADOW_COLOR); g2.fill(shape); g2.translate(-SHADOW_GAP, -SHADOW_GAP); g2.setColor(g2.getBackground()); g2.fill(shape); g2.setColor(oldColor); } private static final Color SHADOW_COLOR = Color.LIGHT_GRAY; public static final int SHADOW_GAP = 4; /** @return the shape to be used for computing the drop shadow */ public Shape getShape() { return null; } /** Adds a persistence delegate to a given encoder that encodes the child nodes of this node. @param encoder the encoder to which to add the delegate */ public static void setPersistenceDelegate(Encoder encoder) { encoder.setPersistenceDelegate(AbstractNode.class, new DefaultPersistenceDelegate() { protected void initialize(Class type, Object oldInstance, Object newInstance, Encoder out) { super.initialize(type, oldInstance, newInstance, out); Node n = (Node)oldInstance; List children = n.getChildren(); for (int i = 0; i < children.size(); i++) { Node c = (Node)children.get(i); out.writeStatement( new Statement(oldInstance, "addChild", new Object[]{ c }) ); } } }); } private ArrayList children; private Node parentNode; }