/*
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.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
A node that has a rectangular shape.
*/
public abstract class RectangularNode extends AbstractNode
{
public Object clone()
{
RectangularNode cloned = (RectangularNode)super.clone();
cloned.bounds = (Rectangle2D)bounds.clone();
return cloned;
}
public void translate(double dx, double dy)
{
bounds.setFrame(bounds.getX() + dx,
bounds.getY() + dy,
bounds.getWidth(),
bounds.getHeight());
super.translate(dx, dy);
}
public boolean contains(Point2D p)
{
return bounds.contains(p);
}
public Rectangle2D getBounds()
{
return (Rectangle2D)bounds.clone();
}
public void setBounds(Rectangle2D newBounds)
{
bounds = newBounds;
}
public void layout(Graph g, Graphics2D g2, Grid grid)
{
grid.snap(bounds);
}
public Point2D getConnectionPoint(Direction d)
{
double slope = bounds.getHeight() / bounds.getWidth();
double ex = d.getX();
double ey = d.getY();
double x = bounds.getCenterX();
double y = bounds.getCenterY();
if (ex != 0 && -slope <= ey / ex && ey / ex <= slope)
{
// intersects at left or right boundary
if (ex > 0)
{
x = bounds.getMaxX();
y += (bounds.getWidth() / 2) * ey / ex;
}
else
{
x = bounds.getX();
y -= (bounds.getWidth() / 2) * ey / ex;
}
}
else if (ey != 0)
{
// intersects at top or bottom
if (ey > 0)
{
x += (bounds.getHeight() / 2) * ex / ey;
y = bounds.getMaxY();
}
else
{
x -= (bounds.getHeight() / 2) * ex / ey;
y = bounds.getY();
}
}
return new Point2D.Double(x, y);
}
private void writeObject(ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
writeRectangularShape(out, bounds);
}
/**
A helper method to overcome the problem that the 2D shapes
aren't serializable. It writes x, y, width and height
to the stream.
@param out the stream
@param s the shape
*/
private static void writeRectangularShape(
ObjectOutputStream out,
RectangularShape s)
throws IOException
{
out.writeDouble(s.getX());
out.writeDouble(s.getY());
out.writeDouble(s.getWidth());
out.writeDouble(s.getHeight());
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
bounds = new Rectangle2D.Double();
readRectangularShape(in, bounds);
}
/**
A helper method to overcome the problem that the 2D shapes
aren't serializable. It reads x, y, width and height
from the stream.
@param in the stream
@param s the shape whose frame is set from the stream values
*/
private static void readRectangularShape(ObjectInputStream in,
RectangularShape s)
throws IOException
{
double x = in.readDouble();
double y = in.readDouble();
double width = in.readDouble();
double height = in.readDouble();
s.setFrame(x, y, width, height);
}
public Shape getShape()
{
return bounds;
}
private transient Rectangle2D bounds;
}