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.BasicStroke; f@0: import java.awt.Color; f@0: import java.awt.Graphics2D; f@0: import java.awt.Stroke; f@0: import java.awt.geom.GeneralPath; f@0: import java.awt.geom.Point2D; f@0: import java.io.IOException; f@0: f@0: /** f@0: This class defines arrowheads of diverse shapes. f@0: */ f@0: public enum ArrowHead { f@0: TAIL("Tail"), f@0: TRIANGLE("Triangle"), f@0: BLACK_TRIANGLE("Black Triangle"), f@0: V("V"), f@0: HALF_V("Half V"), f@0: DIAMOND("Diamond"), f@0: BLACK_DIAMOND("Black Diamond"); f@0: f@0: private ArrowHead(String name) { f@0: this.lowerCaseName = name; f@0: } f@0: f@0: public static ArrowHead getArrowHeadFromString(String arrowHeadName) throws IOException{ f@0: ArrowHead h; f@0: String name = arrowHeadName.toUpperCase().replace(" ", "_"); f@0: try { f@0: h = ArrowHead.valueOf(name); f@0: }catch (IllegalArgumentException e){ f@0: throw new IOException(e); f@0: } f@0: return h; f@0: } f@0: f@0: @Override f@0: public String toString(){ f@0: return lowerCaseName; f@0: } f@0: f@0: /** f@0: Draws the arrowhead. f@0: @param g2 the graphics context f@0: @param p a point on the axis of the arrow head f@0: @param q the end point of the arrow head f@0: */ f@0: public void draw(Graphics2D g2, Point2D p, Point2D q){ f@0: GeneralPath path = getPath(p, q); f@0: Color oldColor = g2.getColor(); f@0: if (this == BLACK_DIAMOND || this == BLACK_TRIANGLE) f@0: g2.setColor(Color.BLACK); f@0: else f@0: g2.setColor(Color.WHITE); f@0: g2.fill(path); f@0: g2.setColor(oldColor); f@0: Stroke oldStroke = g2.getStroke(); f@0: g2.setStroke(new BasicStroke()); f@0: g2.draw(path); f@0: g2.setStroke(oldStroke); f@0: } f@0: f@0: /** f@0: Gets the path of the arrowhead f@0: @param p a point on the axis of the arrow head f@0: @param q the end point of the arrow head f@0: @return the path f@0: */ f@0: public GeneralPath getPath(Point2D p, Point2D q){ f@0: GeneralPath path = new GeneralPath(); f@0: final double ARROW_ANGLE = Math.PI / 6; f@0: final double ARROW_LENGTH = 10; f@0: f@0: double dx = q.getX() - p.getX(); f@0: double dy = q.getY() - p.getY(); f@0: double angle = Math.atan2(dy, dx); f@0: double x1 = q.getX() f@0: - ARROW_LENGTH * Math.cos(angle + ARROW_ANGLE); f@0: double y1 = q.getY() f@0: - ARROW_LENGTH * Math.sin(angle + ARROW_ANGLE); f@0: double x2 = q.getX() f@0: - ARROW_LENGTH * Math.cos(angle - ARROW_ANGLE); f@0: double y2 = q.getY() f@0: - ARROW_LENGTH * Math.sin(angle - ARROW_ANGLE); f@0: f@0: path.moveTo((float)q.getX(), (float)q.getY()); f@0: path.lineTo((float)x1, (float)y1); f@0: if (this == V) f@0: { f@0: path.moveTo((float)x2, (float)y2); f@0: path.lineTo((float)q.getX(), (float)q.getY()); f@0: } f@0: else if (this == TRIANGLE || this == BLACK_TRIANGLE) f@0: { f@0: path.lineTo((float)x2, (float)y2); f@0: path.closePath(); f@0: } f@0: else if (this == DIAMOND || this == BLACK_DIAMOND) f@0: { f@0: double x3 = x2 - ARROW_LENGTH * Math.cos(angle + ARROW_ANGLE); f@0: double y3 = y2 - ARROW_LENGTH * Math.sin(angle + ARROW_ANGLE); f@0: path.lineTo((float)x3, (float)y3); f@0: path.lineTo((float)x2, (float)y2); f@0: path.closePath(); f@0: } f@0: return path; f@0: } f@0: f@0: private String lowerCaseName; f@0: }