package org.archstudio.bna.things.labels; import java.awt.Dimension; import java.awt.Font; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import org.archstudio.bna.IBNAView; import org.archstudio.bna.ICoordinate; import org.archstudio.bna.ICoordinateMapper; import org.archstudio.bna.things.AbstractThingPeer; import org.archstudio.bna.ui.IUIResources; import org.archstudio.bna.utils.BNAUtils; import org.archstudio.swtutils.constants.HorizontalAlignment; import org.archstudio.swtutils.constants.LineStyle; import org.archstudio.swtutils.constants.VerticalAlignment; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; public class AnchoredLabelThingPeer<T extends AnchoredLabelThing> extends AbstractThingPeer<T> { private static final boolean DEBUG = false; Shape lastTextLocalShape = null; int SPACING = 4; public AnchoredLabelThingPeer(T thing, IBNAView view, ICoordinateMapper cm) { super(thing, view, cm); } @Override public boolean draw(Rectangle localBounds, IUIResources r) { String text = t.getText().trim(); if (text.length() == 0) { return false; } int angle = t.getAngle(); HorizontalAlignment horizontal = t.getHorizontalAlignment(); VerticalAlignment vertical = t.getVerticalAlignment(); Point2D ap = t.getAnchorPoint(); Point2D ip = t.getIndicatorPoint(); Font font = r.getFont(t.getFontName(), t.getFontStyle(), t.getFontSize()); Dimension size = r.getTextSize(font, text); double offsetX = -size.width / 2d + horizontal.getDelta() * (size.width / 2d); double offsetY = -size.height / 2d + vertical.getDelta() * (size.height / 2d); offsetY -= r.getFontMetrics(font).getLeading(); Rectangle2D bounds = new Rectangle2D.Double(offsetX, offsetY, size.width, size.height); AffineTransform transform = new AffineTransform(); transform.translate(ap.getX(), ap.getY()); transform.rotate(Math.PI * angle / 180); Path2D boundsPath = new Path2D.Double(bounds); boundsPath.transform(transform); t.setBoundingBox(BNAUtils.toRectangle(boundsPath.getBounds())); RGB color = t.getColor(); if (color != null) { Point2D lap = cm.worldToLocal(ap); Point2D lip = ip != null ? cm.worldToLocal(ip) : null; int lfontsize = (int) (t.getFontSize() * cm.getLocalScale()); Font lfont = lfontsize > 2 ? r.getFont(t.getFontName(), t.getFontStyle(), lfontsize) : null; Dimension lsize = lfont == null ? new Dimension(0, 0) : r.getTextSize(lfont, text); double loffsetX = -lsize.width / 2d + horizontal.getDelta() * (lsize.width / 2d); double loffsetY = -lsize.height / 2d + vertical.getDelta() * (lsize.height / 2d); loffsetY -= lfont == null ? 0 : r.getFontMetrics(lfont).getLeading(); if (lfont != null) { Rectangle2D lbounds = new Rectangle2D.Double(loffsetX, loffsetY, lsize.width, lsize.height); AffineTransform lTransform = new AffineTransform(); lTransform.translate(lap.getX(), lap.getY()); lTransform.rotate(Math.PI * angle / 180); Path2D lBoundsPath = new Path2D.Double(lbounds); lBoundsPath.transform(lTransform); lastTextLocalShape = lBoundsPath; if (DEBUG) { r.drawShape(lastTextLocalShape, new RGB(0, 0, 0), 1, LineStyle.SOLID, 1); } r.pushMatrix(lap.getX(), lap.getY(), Math.PI * angle / 180); try { r.drawText(lfont, text, loffsetX, loffsetY, t.getColor(), 1); } finally { r.popMatrix(); } RGB edgeColor = t.getEdgeColor(); if (lip != null && edgeColor != null) { double spacing = SPACING * cm.getLocalScale(); Point2D lap2d1 = new Point2D.Double(lbounds.getMinX() - spacing, lbounds.getCenterY()); Point2D lap2d2 = new Point2D.Double(lbounds.getMaxX() + spacing, lbounds.getCenterY()); Point2D lip2D = lip; lTransform.transform(lap2d1, lap2d1); lTransform.transform(lap2d2, lap2d2); double dist1 = lap2d1.distance(lip2D); double dist2 = lap2d2.distance(lip2D); Point2D fromPoint = dist1 < dist2 ? lap2d1 : lap2d2; Line2D.Double line = new Line2D.Double(fromPoint, lip2D); r.drawShape(line, edgeColor, t.getLineWidth(), t.getLineStyle(), 1); } } else { lastTextLocalShape = new Rectangle2D.Double(lap.getX() - 2, lap.getY() - 2, 4, 4); if (lip != null) { Line2D.Double line = new Line2D.Double(lip, lap); r.drawShape(line, t.getEdgeColor(), t.getLineWidth(), t.getLineStyle(), 1); } } } return true; } @Override public boolean isInThing(ICoordinate location) { if (lastTextLocalShape != null) { Point lPoint = location.getLocalPoint(); return lastTextLocalShape.contains(lPoint.x, lPoint.y); } return false; } }