/* ******************************************************************************
* 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.fishbone.decorations;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.widgets.Display;
import org.xmind.gef.draw2d.IRotatableReferencedFigure;
import org.xmind.gef.draw2d.geometry.PrecisionLine;
import org.xmind.gef.draw2d.geometry.PrecisionLine.LineType;
import org.xmind.gef.draw2d.geometry.PrecisionPoint;
import org.xmind.gef.draw2d.geometry.PrecisionPointList;
import org.xmind.gef.draw2d.geometry.PrecisionPolygon;
import org.xmind.gef.draw2d.geometry.PrecisionRectangle;
import org.xmind.gef.draw2d.geometry.PrecisionRotator;
import org.xmind.gef.draw2d.graphics.GradientPattern;
import org.xmind.gef.draw2d.graphics.Path;
import org.xmind.ui.decorations.AbstractTopicDecoration;
import org.xmind.ui.resources.ColorUtils;
public class FishboneTopicDecoration extends AbstractTopicDecoration {
private static final Point CENTER = new Point(0, 0);
private PrecisionRotator rotator = null;
private PrecisionPolygon points = null;
protected PrecisionRotator r() {
if (rotator == null) {
rotator = new PrecisionRotator();
}
return rotator;
}
public void invalidate() {
points = null;
super.invalidate();
}
public void validate(IFigure figure) {
if (points == null)
points = calcPoints(figure);
super.validate(figure);
}
private PrecisionPolygon calcPoints(IFigure figure) {
PrecisionPolygon polygon = new PrecisionPolygon(4);
IRotatableReferencedFigure rf = (IRotatableReferencedFigure) figure;
r().setAngle(rf.getRotationDegrees());
r().setOrigin(CENTER.x, CENTER.y);
PrecisionRectangle bounds = rf.getNormalPreferredBounds(CENTER)
.getExpanded(-getLineWidth(), -getLineWidth());
polygon.setPoint(r().tp(bounds.getTopLeft()), 0);
polygon.setPoint(r().tp(bounds.getTopRight()), 1);
polygon.setPoint(r().tp(bounds.getBottomRight()), 2);
polygon.setPoint(r().tp(bounds.getBottomLeft()), 3);
return polygon;
}
protected void sketch(IFigure figure, Path shape, Rectangle box,
int purpose) {
double cx = box.x + box.width * 0.5d;
double cy = box.y + box.height * 0.5d;
if (points == null)
points = calcPoints(figure);
PrecisionPoint p = points.getPoint(0);
shape.moveTo((float) (cx + p.x), (float) (cy + p.y));
for (int i = 1; i < 4; i++) {
lineTo(shape, cx, cy, points.getPoint(i));
}
shape.close();
}
private void lineTo(Path shape, double cx, double cy, PrecisionPoint p) {
shape.lineTo((float) (cx + p.x), (float) (cy + p.y));
}
protected Pattern createGradientPattern(IFigure figure, int alpha,
Color bgColor) {
return super.createGradientPattern(figure, alpha, bgColor);
}
/**
* Create oblique background pattern for fishbone topics.
*
* @param figure
* the figure
* @param alpha
* the alpha
* @param color
* the color
*
* @return a new gradient pattern
* @deprecated The gradient pattern on carbon (Mac OS X 10.6+) creates
* gradient "blocks" when the starting point is not
* vertical/horizontal to the ending point.
*/
protected Pattern createObliquePattern(IFigure figure, int alpha,
Color color) {
Rectangle b = figure.getBounds();
double cx = b.x + b.width * 0.5;
double cy = b.y + b.height * 0.5;
PrecisionPoint p1 = points.getPoint(0);
PrecisionPoint p2 = points.getPoint(3);
Pattern p = new GradientPattern(Display.getCurrent(), //
(float) (cx + p1.x), (float) (cy + p1.y), //
(float) (cx + p2.x), (float) (cy + p2.y), //
ColorUtils.gradientLighter(color), alpha, //
color, alpha);
return p;
}
protected void paintOutline(IFigure figure, Graphics graphics) {
// don't paint outline
}
protected PrecisionPoint getEast(IFigure figure, double expansion) {
PrecisionPoint center = new PrecisionPoint(
figure.getBounds().getCenter());
return center.translate(points.getPoint(2));
}
protected PrecisionPoint getWest(IFigure figure, double expansion) {
PrecisionPoint center = new PrecisionPoint(
figure.getBounds().getCenter());
return center.translate(points.getPoint(3));
}
protected PrecisionPoint getNorth(IFigure figure, double expansion) {
PrecisionPoint center = new PrecisionPoint(
figure.getBounds().getCenter());
return center
.translate(points.getPoint(0).getCenter(points.getPoint(1)));
}
protected PrecisionPoint getSouth(IFigure figure, double expansion) {
PrecisionPoint center = new PrecisionPoint(
figure.getBounds().getCenter());
return center
.translate(points.getPoint(3).getCenter(points.getPoint(2)));
}
public PrecisionPoint getAnchorLocation(IFigure figure, double refX,
double refY, double expansion) {
checkValidation(figure);
Rectangle r = figure.getBounds();
double cx = r.x + r.width * 0.5d;
double cy = r.y + r.height * 0.5d;
PrecisionLine ray = new PrecisionLine(cx, cy, refX, refY, LineType.Ray);
PrecisionPolygon polygon = points.getCopy();
polygon.translate(cx, cy);
PrecisionPointList result = polygon.intersect(ray, 0.000001);
if (result.isEmpty())
return polygon.getPoint(0);
return result.getPoint(0);
}
}