package org.archstudio.bna.things.labels; import java.awt.Insets; import java.awt.Shape; import java.awt.geom.Path2D; 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.Flow; import org.archstudio.swtutils.constants.Orientation; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; public class DirectionalLabelThingPeer<T extends DirectionalLabelThing> extends AbstractThingPeer<T> { protected Shape createTriangle(Orientation o, Rectangle lbb) { int n = 2; int d = 3; int x1 = lbb.x; int y1 = lbb.y; int xm = x1 + lbb.width / 2 + 1; int ym = y1 + lbb.height / 2 + 1; int x2 = x1 + lbb.width + 1; int y2 = y1 + lbb.height + 1; int xl = x1 + lbb.width * n / d; int yl = y1 + lbb.height * n / d; int xg = x1 + lbb.width - lbb.width * n / d; int yg = y1 + lbb.height - lbb.height * n / d; Point p1, p2, p3; switch (o) { case NORTH: p1 = new Point(x1, y2); p3 = new Point(xm, y1); p2 = new Point(x2, y2); break; case EAST: p1 = new Point(x1, y1); p3 = new Point(x2, ym); p2 = new Point(x1, y2); break; case SOUTH: p2 = new Point(x2, y1); p3 = new Point(xm, y2); p1 = new Point(x1, y1); break; case WEST: p2 = new Point(x2, y2); p3 = new Point(x1, ym); p1 = new Point(x2, y1); break; case NORTHEAST: p1 = new Point(x1, yg); p2 = new Point(x2, y1); p3 = new Point(xl, y2); break; case SOUTHEAST: p1 = new Point(xl, y1); p2 = new Point(x2, y2); p3 = new Point(x1, yl); break; case SOUTHWEST: p1 = new Point(x2, yl); p2 = new Point(x1, y2); p3 = new Point(xg, y1); break; case NORTHWEST: p1 = new Point(xg, y2); p2 = new Point(x1, y1); p3 = new Point(x2, yg); break; default: throw new IllegalArgumentException(o.toString()); } Path2D shape = new Path2D.Double(); shape.moveTo(p1.x, p1.y); shape.lineTo(p2.x, p2.y); shape.lineTo(p3.x, p3.y); shape.closePath(); return shape; } public DirectionalLabelThingPeer(T thing, IBNAView view, ICoordinateMapper cm) { super(thing, view, cm); } Flow flow; Orientation orientation; @Override public boolean draw(Rectangle localBounds, IUIResources r) { Rectangle lbb = cm.worldToLocal(t.getBoundingBox()); if (!localBounds.intersects(lbb)) { return false; } Insets insets = t.getLocalInsets(); lbb.x += insets.left; lbb.y += insets.top; lbb.width -= insets.left + insets.right; lbb.height -= insets.top + insets.bottom; //r.drawShape(BNAUtils.toRectangle2D(lbb), new RGB(255, 0, 0), 1); flow = t.getFlow(); if (flow == Flow.NONE) { return false; } orientation = t.getOrientation(); if (orientation == Orientation.NONE) { return false; } RGB color = t.getColor(); if (color != null) { int n = 1; int d = 4; int x1 = lbb.x; int y1 = lbb.y; int x2 = x1 + lbb.width + 1; int y2 = y1 + lbb.height + 1; int xl = x1 + lbb.width * n / d; int yl = y1 + lbb.height * n / d; int xg = x1 + lbb.width - lbb.width * n / d; int yg = y1 + lbb.height - lbb.height * n / d; switch (flow) { case IN: /* * For "in" facing flows, the triangle points in the opposite direction. */ r.fillShape(createTriangle(orientation.getOpposite(), lbb), color, null, 1); break; case OUT: r.fillShape(createTriangle(orientation, lbb), color, null, 1); break; case INOUT: { switch (orientation) { case NORTH: case SOUTH: { Rectangle a = BNAUtils.clone(lbb); int height = a.height; a.height = a.height / 2 - 1; r.fillShape(createTriangle(Orientation.NORTH, a), color, null, 1); a.y += height / 2 + 1; r.fillShape(createTriangle(Orientation.SOUTH, a), color, null, 1); } break; case EAST: case WEST: { Rectangle a = BNAUtils.clone(lbb); int width = a.width; a.width = a.width / 2 - 1; r.fillShape(createTriangle(Orientation.WEST, a), color, null, 1); a.x += width / 2 + 1; r.fillShape(createTriangle(Orientation.EAST, a), color, null, 1); } break; case NORTHWEST: case SOUTHEAST: { Path2D shape; shape = new Path2D.Double(); shape.moveTo(xl - 0.5, yg - 0.5); shape.lineTo(x1, y1); shape.lineTo(xg - 0.5, yl - 0.5); shape.closePath(); r.fillShape(shape, color, null, 1); shape = new Path2D.Double(); shape.moveTo(xg + 0.5, yl + 0.5); shape.lineTo(x2, y2); shape.lineTo(xl + 0.5, yg + 0.5); shape.closePath(); r.fillShape(shape, color, null, 1); } break; case NORTHEAST: case SOUTHWEST: { Path2D shape; shape = new Path2D.Double(); shape.moveTo(xl + 0.5, yl - 0.5); shape.lineTo(x2, y1); shape.lineTo(xg + 0.5, yg - 0.5); shape.closePath(); r.fillShape(shape, color, null, 1); shape = new Path2D.Double(); shape.moveTo(xg - 0.5, yg + 0.5); shape.lineTo(x1, y2); shape.lineTo(xl - 0.5, yl + 0.5); shape.closePath(); r.fillShape(shape, color, null, 1); } break; default: throw new IllegalArgumentException(orientation.toString()); } } break; default: throw new IllegalArgumentException(flow.toString()); } } return true; } @Override public boolean isInThing(ICoordinate location) { return t.getBoundingBox().contains(location.getWorldPoint()); } }