package org.xmind.ui.internal.decorations;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionDimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Display;
import org.xmind.gef.draw2d.geometry.Geometry;
import org.xmind.gef.draw2d.geometry.PrecisionPoint;
import org.xmind.gef.draw2d.graphics.GraphicsUtils;
import org.xmind.gef.draw2d.graphics.Path;
import org.xmind.ui.decorations.AbstractTopicDecoration;
import org.xmind.ui.internal.svgsupport.SvgPathParser;
public class CloudTopicDecoration extends AbstractTopicDecoration {
private static final float scaleLeft = 0.17f;
private static final float scaleRight = 0.16f;
private static final float scaleTop = 0.22f;
private static final float scaleBottom = 0.27f;
private static final float RATIO = 2.5f;
private String svgPath;
public CloudTopicDecoration() {
}
public CloudTopicDecoration(String id) {
super(id);
}
public CloudTopicDecoration(String id, String svgPath) {
super(id);
this.svgPath = svgPath;
}
protected void sketch(IFigure figure, Path shape, Rectangle box,
int purpose) {
Path path = new Path(Display.getCurrent());
SvgPathParser parser = SvgPathParser.getInstance();
float halfLineWidth = getLineWidth() * 0.5f;
if (purpose == CHECK) {
parser.parseSvgPath(path, box.getCenter().x - halfLineWidth,
box.getCenter().y + halfLineWidth,
box.width + getLineWidth(), box.height + getLineWidth(),
svgPath);
} else {
parser.parseSvgPath(path, box.getCenter().x + 1,
box.getCenter().y + 1, box.width, box.height, svgPath);
}
shape.addPath(path);
path.close();
}
public PrecisionPoint getAnchorLocation(IFigure figure, double refX,
double refY, double expansion) {
float scaleWidth = 1 - scaleLeft - scaleRight;
float scaleHeight = 1 - scaleTop - scaleBottom;
Rectangle bounds = figure.getBounds();
Point tf = bounds.getTopLeft().getTranslated(bounds.width * scaleLeft,
bounds.height * scaleTop);
Rectangle area = new Rectangle(tf.x, tf.y,
(int) (bounds.width * scaleWidth),
(int) (bounds.height * scaleHeight));
PrecisionPoint p1 = Geometry.getChopBoxLocation(refX, refY, area,
expansion);
PrecisionPoint p2 = Geometry.getChopBoxLocation(refX, refY,
getOutlineBox(figure), expansion);
return calcAnchorLocation(figure, p1, p2);
}
private PrecisionPoint calcAnchorLocation(IFigure figure, PrecisionPoint p1,
PrecisionPoint p2) {
if (p1.getDistance(p2) < (getLineWidth() == 0 ? 1 : getLineWidth()))
return p2;
PrecisionPoint p3 = new PrecisionPoint((p1.x + p2.x) / 2,
(p1.y + p2.y) / 2);
if (containsPoint(figure, (float) p3.x, (float) p3.y))
return calcAnchorLocation(figure, p3, p2);
else
return calcAnchorLocation(figure, p1, p3);
}
private boolean containsPoint(IFigure figure, float x, float y) {
checkValidation(figure);
GC gc = GraphicsUtils.getAdvanced().getGC();
gc.setLineWidth(getCheckingLineWidth());
Path shape = new Path(Display.getCurrent());
sketch(figure, shape, getOutlineBox(figure), FILL);
boolean ret = shape.contains(x, y, gc, false);
shape.close();
shape.dispose();
return ret;
}
public Insets getPreferredInsets(IFigure figure, int width, int height) {
float scaleWidth = 1 - scaleLeft - scaleRight;
float scaleHeight = 1 - scaleTop - scaleBottom;
Insets insets = new Insets(
(int) ((height + getTopMargin() + getLineWidth()) / scaleHeight
* scaleTop),
(int) ((width + getLeftMargin() + getLineWidth()) / scaleWidth
* scaleLeft),
(int) ((height + getBottomMargin() + getLineWidth())
/ scaleHeight * scaleBottom),
(int) ((width + getRightMargin() + getLineWidth()) / scaleWidth
* scaleRight));
PrecisionDimension dimension = expandWHitAsRatio(
new PrecisionDimension(width + insets.left + insets.right,
height + insets.top + insets.bottom));
Insets inset = new Insets();
inset.top = (int) ((dimension.height - height) * scaleTop
/ (scaleTop + scaleBottom));
inset.left = (int) ((dimension.width - width) * scaleLeft
/ (scaleLeft + scaleRight));
inset.bottom = (int) ((dimension.height - height) * scaleBottom
/ (scaleTop + scaleBottom));
inset.right = (int) ((dimension.width - width) * scaleRight
/ (scaleLeft + scaleRight));
return inset;
}
private PrecisionDimension expandWHitAsRatio(
PrecisionDimension whitDimension) {
PrecisionDimension dimension = whitDimension;
if (whitDimension.width > whitDimension.height * RATIO) {
dimension.height = (int) Math.ceil(whitDimension.width / RATIO);
dimension.width = (int) (dimension.height * RATIO);
} else if (whitDimension.width < whitDimension.height * RATIO) {
dimension.width = (int) Math.ceil(whitDimension.height * RATIO);
}
return dimension;
}
}