/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.model.drawing;
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import java.util.List;
import com.t3.xstreamversioned.version.SerializationVersion;
/**
* @author drice
*/
@SerializationVersion(0)
public class LineSegment extends AbstractDrawing {
private final List<Point> points = new ArrayList<Point>();
private Float width;
private transient int lastPointCount = -1;
private transient Rectangle cachedBounds;
private transient Area area;
public LineSegment(float width) {
this.width = width;
}
/**
* Manipulate the points by calling {@link #getPoints} and then adding {@link Point} objects to the returned
* {@link List}.
*/
public List<Point> getPoints() {
// This is really, really ugly, but we need to flush the area on any change to the shape
// and typically the reason for calling this method is to change the list
area = null;
return points;
}
@Override
public Area getArea() {
if (area == null) {
area = createLineArea();
}
return area;
}
private Area createLineArea() {
GeneralPath gp = null;
for (Point point : points) {
if (gp == null) {
gp = new GeneralPath();
gp.moveTo(point.x, point.y);
continue;
}
gp.lineTo(point.x, point.y);
}
BasicStroke stroke = new BasicStroke(width != null ? width : 2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
return new Area(stroke.createStrokedShape(gp));
}
@Override
protected void draw(Graphics2D g) {
if (width == null) {
// Handle legacy values
area = null; // reset, build with new value
width = ((BasicStroke) g.getStroke()).getLineWidth();
}
Area area = getArea();
g.fill(area);
}
@Override
protected void drawBackground(Graphics2D g) {
// do nothing
}
/*
* (non-Javadoc)
*
* @see com.t3.model.drawing.Drawable#getBounds()
*/
@Override
public Rectangle getBounds() {
if (lastPointCount == points.size()) {
return cachedBounds;
}
Rectangle bounds = new Rectangle(points.get(0));
for (Point point : points) {
bounds.add(point);
}
// Special casing
if (bounds.width < 1) {
bounds.width = 1;
}
if (bounds.height < 1) {
bounds.height = 1;
}
cachedBounds = bounds;
lastPointCount = points.size();
return bounds;
}
}