f@0: /* f@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool f@0: f@0: Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) f@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) f@0: f@0: This program is free software: you can redistribute it and/or modify f@0: it under the terms of the GNU General Public License as published by f@0: the Free Software Foundation, either version 3 of the License, or f@0: (at your option) any later version. f@0: f@0: This program is distributed in the hope that it will be useful, f@0: but WITHOUT ANY WARRANTY; without even the implied warranty of f@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@0: GNU General Public License for more details. f@0: f@0: You should have received a copy of the GNU General Public License f@0: along with this program. If not, see . f@0: */ f@0: f@0: package uk.ac.qmul.eecs.ccmi.simpletemplate; f@0: f@0: import java.awt.Color; f@0: import java.awt.Dimension; f@0: import java.awt.Graphics2D; f@0: import java.awt.geom.Point2D; f@0: import java.awt.geom.Rectangle2D; f@0: f@0: import javax.swing.JLabel; f@0: f@0: import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramTreeNode; f@0: import uk.ac.qmul.eecs.ccmi.gui.GraphPanel; f@0: f@0: f@0: /** f@0: * Provides static methods to draw a {@code SimpleShapeEdge} on a {@code Graphics} f@0: * f@0: */ f@0: public abstract class EdgeDrawSupport { f@0: /** f@0: * Draws a string in proximity of a edge. f@0: * @param g2 the graphics context f@0: * @param p an endpoint of the segment along which to f@0: * draw the string f@0: * @param q the other endpoint of the segment along which to f@0: * draw the string f@0: * @param arrow the arrow head painted on the edge end where the string f@0: * is to be painted f@0: * @param s the string to draw f@0: * @param center true if the string should be centered f@0: * along the segment f@0: */ f@0: f@0: public static void drawString(Graphics2D g2, f@0: Point2D p, Point2D q, ArrowHead arrow, String s, boolean center){ f@0: if (s == null || s.length() == 0) return; f@0: label.setText("" + s + ""); f@0: label.setFont(g2.getFont()); f@0: Dimension d = label.getPreferredSize(); f@0: label.setBounds(0, 0, d.width, d.height); f@0: f@0: Rectangle2D b = getStringBounds(g2, p, q, arrow, s, center); f@0: f@0: Color oldColor = g2.getColor(); f@0: g2.setColor(g2.getBackground()); f@0: g2.fill(b); f@0: g2.setColor(oldColor); f@0: f@0: g2.translate(b.getX(), b.getY()); f@0: label.paint(g2); f@0: g2.translate(-b.getX(), -b.getY()); f@0: } f@0: f@0: /** f@0: * Draws a graphical marker when the edge has notes associated to it f@0: * @see uk.ac.qmul.eecs.ccmi.diagrammodel.TreeModel#setNotes(DiagramTreeNode, String, Object) f@0: * f@0: * @param g2 the graphics context f@0: * @param p an endpoint of the segment along which to draw the string f@0: * @param q the other endpoint of the segment along which to draw the string f@0: */ f@0: public static void drawMarker(Graphics2D g2, Point2D p, Point2D q){ f@0: Point2D attach = q; f@0: if (p.getX() > q.getX()){ f@0: drawMarker(g2, q, p); f@0: return; f@0: } f@0: attach = new Point2D.Double((p.getX() + q.getX()) / 2, f@0: (p.getY() + q.getY()) / 2); f@0: Color oldColor = g2.getColor(); f@0: g2.setColor(GraphPanel.GRABBER_COLOR); f@0: g2.fill(new Rectangle2D.Double(attach.getX() - MARKER_SIZE / 2, attach.getY() - MARKER_SIZE / 2, MARKER_SIZE, MARKER_SIZE)); f@0: g2.setColor(oldColor); f@0: } f@0: f@0: /* f@0: Computes the attachment point for drawing a string. f@0: return the point at which to draw the string f@0: */ f@0: private static Point2D getAttachmentPoint(Graphics2D g2, f@0: Point2D p, Point2D q, ArrowHead arrow, Dimension d, boolean center){ f@0: final int GAP = 3; f@0: double xoff = GAP; f@0: double yoff = -GAP - d.getHeight(); f@0: Point2D attach = q; f@0: if (center){ f@0: if (p.getX() > q.getX()){ f@0: return getAttachmentPoint(g2, q, p, arrow, d, center); f@0: } f@0: attach = new Point2D.Double((p.getX() + q.getX()) / 2, f@0: (p.getY() + q.getY()) / 2); f@0: if (p.getY() < q.getY()) f@0: yoff = - GAP - d.getHeight(); f@0: else if (p.getY() == q.getY()) f@0: xoff = -d.getWidth() / 2; f@0: else f@0: yoff = GAP; f@0: } f@0: else f@0: { f@0: if (p.getX() < q.getX()){ f@0: xoff = -GAP - d.getWidth(); f@0: } f@0: if (p.getY() > q.getY()){ f@0: yoff = GAP; f@0: } f@0: if (arrow != null){ f@0: Rectangle2D arrowBounds = arrow.getPath(p, q).getBounds2D(); f@0: if (p.getX() < q.getX()){ f@0: xoff -= arrowBounds.getWidth(); f@0: } f@0: else{ f@0: xoff += arrowBounds.getWidth(); f@0: } f@0: } f@0: } f@0: return new Point2D.Double(attach.getX() + xoff, attach.getY() + yoff); f@0: } f@0: f@0: /* f@0: * Computes the extent of a string that is drawn along a line segment. f@0: * The rectangle enclosing the string f@0: */ f@0: private static Rectangle2D getStringBounds(Graphics2D g2, f@0: Point2D p, Point2D q, ArrowHead arrow, String s, boolean center){ f@0: if (g2 == null) return new Rectangle2D.Double(); f@0: if (s == null || s.equals("")) return new Rectangle2D.Double(q.getX(), q.getY(), 0, 0); f@0: label.setText("" + s + ""); f@0: label.setFont(g2.getFont()); f@0: Dimension d = label.getPreferredSize(); f@0: Point2D a = getAttachmentPoint(g2, p, q, arrow, d, center); f@0: return new Rectangle2D.Double(a.getX(), a.getY(), d.getWidth(), d.getHeight()); f@0: } f@0: f@0: /* size of the marker when an edge as notes */ f@0: private static final int MARKER_SIZE = 7; f@0: private static JLabel label = new JLabel(); f@0: }