package com.trickl.graph.ext; import java.awt.*; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import org.jgraph.graph.*; public class HexagonVertexView extends VertexView { // Define the Renderer for an HexagonView static class HexagonRenderer extends VertexRenderer { @Override public void paint(Graphics g) { Graphics2D g2D = (Graphics2D) g; Dimension size = getSize(); boolean wasSelected = selected; int interiorWidth = size.width + 2 * borderWidth; int interiorHeight = size.height - borderWidth; int[] xPoints = {-borderWidth, -borderWidth + interiorWidth / 4, -borderWidth + (interiorWidth * 3) / 4, -borderWidth + interiorWidth, -borderWidth +(interiorWidth * 3) / 4, -borderWidth + interiorWidth / 4}; int[] yPoints = {interiorHeight / 2, 0, 0, interiorHeight / 2, interiorHeight, interiorHeight}; // if the GraphCell is set opaque (via GraphConstants.setOpaque(), // then paint a background. If a gradient color is set and it is not // the preview (during drag&drop of the cell) paint a gradient pane if (super.isOpaque()) { g.setColor(super.getBackground()); if (gradientColor != null && !preview) { setOpaque(false); g2D.setPaint(new GradientPaint(0, 0, getBackground(), getWidth(), getHeight(), gradientColor, true)); } g.fillPolygon(xPoints, yPoints, xPoints.length); } try { setBorder(null); setOpaque(false); selected = false; super.paint(g); } finally { selected = wasSelected; } if (!selected) { if (bordercolor == null) bordercolor = Color.BLACK; g.setColor(bordercolor); g2D.setStroke(new BasicStroke(borderWidth)); g.drawPolygon(xPoints, yPoints, xPoints.length); } else { g2D.setStroke(GraphConstants.SELECTION_STROKE); g.setColor(highlightColor); g.drawPolygon(xPoints, yPoints, xPoints.length); } } /** * Returns the intersection of the bounding rectangle and the straight line * between the source and the specified point p. The specified point is * expected not to intersect the bounds. */ @Override public Point2D getPerimeterPoint(VertexView view, Point2D source, Point2D p) { Rectangle2D bounds = view.getBounds(); double x = bounds.getX(); double y = bounds.getY(); double width = bounds.getWidth(); double height = bounds.getHeight(); double xCenter = x + width / 2; double yCenter = y + height / 2; double dx = p.getX() - xCenter; // Compute Angle double dy = p.getY() - yCenter; double alpha = Math.atan2(dy, dx); double beta = (Math.PI / 2.) - alpha; double theta = Math.atan2(height, width / 2); double gamma = Math.PI - alpha - Math.PI / 3; double delta = Math.PI + alpha - Math.PI / 3; double xout = 0, yout = 0; if (alpha > Math.PI - theta) { // Bottom Left xout = x - width * Math.sin(alpha) / (4 * Math.sin(delta)); yout = yCenter - Math.sqrt(3) * width * Math.sin(alpha) / (4 * Math.sin(delta)); } else if (alpha < -Math.PI + theta) { // Top Left xout = x + width * Math.sin(alpha) / (4 * Math.sin(gamma)); yout = yCenter - Math.sqrt(3) * width * Math.sin(alpha) / (4 * Math.sin(gamma)); } else if (alpha < -theta) { // Top xout = xCenter - height * Math.tan(beta) / 2; yout = y; } else if (alpha > theta) { // Bottom xout = xCenter + height * Math.tan(beta) / 2; yout = y + height; } else if (alpha > 0) { // Bottom Right xout = x + width - width * Math.sin(alpha) / (4 * Math.sin(gamma)); yout = yCenter + Math.sqrt(3) * width * Math.sin(alpha) / (4 * Math.sin(gamma)); } else if (alpha < 0) { // Top Right xout = x + width + width * Math.sin(alpha) / (4 * Math.sin(delta)); yout = yCenter + Math.sqrt(3) * width * Math.sin(alpha) / (4 * Math.sin(delta)); } return new Point2D.Double(xout, yout); } } static HexagonRenderer hexagonRenderer = new HexagonRenderer(); // Constructor for Superclass public HexagonVertexView(Object cell) { super(cell); } // Returns Perimeter Point for Hexagons @Override public Point2D getPerimeterPoint(EdgeView edge, Point2D source, Point2D p) { return hexagonRenderer.getPerimeterPoint(this, source, p); } // Returns the Renderer for this View @Override public CellViewRenderer getRenderer() { return hexagonRenderer; } }