/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.decorations;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.xmind.gef.draw2d.decoration.ICorneredDecoration;
import org.xmind.gef.draw2d.graphics.Path;
import org.xmind.ui.mindmap.IBoundaryPart;
public class RoundedPolygonBoundaryDecoration extends PolygonBoundaryDecoration
implements ICorneredDecoration {
private static final float CORNER_CONTROL_RATIO = 0.447715f;
private IBoundaryPart boundary;
private int cornerSize = 0;
public RoundedPolygonBoundaryDecoration() {
super();
}
public RoundedPolygonBoundaryDecoration(IBoundaryPart boundary, String id) {
super(id);
this.boundary = boundary;
}
protected void sketch(IFigure figure, Path shape, Rectangle box,
int purpose) {
List<Point> points = calcPathPoints(box, boundary);
int c = getAppliedCornerSize();
if (points.size() > 4) {
if (c == 0) {
shape.moveTo(points.get(0));
for (int i = 1; i < points.size(); i++)
shape.lineTo(points.get(i));
shape.lineTo(points.get(0));
shape.close();
} else {
Point p0 = calcRoundedPoint(points.get(0),
points.get(points.size() - 1), c);
Point p1 = null;
Point c1, c2;
shape.moveTo(p0);
for (int i = 0; i < points.size() - 1; i++) {
p1 = calcRoundedPoint(points.get(i), points.get(i + 1), c);
c1 = calcControlPoint(p0, points.get(i));
c2 = calcControlPoint(p1, points.get(i));
// shape.lineTo(p1);
shape.cubicTo(c1, c2, p1);
p0 = calcRoundedPoint(points.get(i + 1), points.get(i), c);
shape.lineTo(p0);
}
p1 = calcRoundedPoint(points.get(points.size() - 1),
points.get(0), c);
// shape.lineTo(p1);
c1 = calcControlPoint(p0, points.get(points.size() - 1));
c2 = calcControlPoint(p1, points.get(points.size() - 1));
shape.cubicTo(c1, c2, p1);
p0 = calcRoundedPoint(points.get(0),
points.get(points.size() - 1), c);
shape.lineTo(p0);
shape.close();
}
} else {
if (c == 0) {
shape.addRectangle(box);
} else {
shape.addRoundedRectangle(box, c);
}
}
}
private Point calcRoundedPoint(Point p1, Point p2, int corner) {
int dx = p2.x - p1.x;
int dy = p2.y - p1.y;
if (dx == 0) {
if (dy > 0)
return p1.getTranslated(0, corner);
return p1.getTranslated(0, -corner);
} else if (dy == 0) {
if (dx > 0)
return p1.getTranslated(corner, 0);
return p1.getTranslated(-corner, 0);
} else {
double l = p1.getDistance(p2);
double x = dx / l * corner;
double y = dy / l * corner;
return p1.getTranslated(x, y);
}
}
private Point calcControlPoint(Point p1, Point p2) {
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
return p1.getTranslated(dx * CORNER_CONTROL_RATIO,
dy * CORNER_CONTROL_RATIO);
}
public int getCornerSize() {
return cornerSize;
}
private int getAppliedCornerSize() {
return getCornerSize();
}
public void setCornerSize(IFigure figure, int cornerSize) {
if (cornerSize == this.cornerSize)
return;
this.cornerSize = cornerSize;
invalidate();
if (figure != null) {
figure.revalidate();
figure.repaint();
}
}
}