001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.uml.ui.products.ad.viewfactory;
043:
044: import java.awt.Shape;
045: import java.awt.geom.AffineTransform;
046: import java.awt.Color;
047:
048: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawInfo;
049: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead;
050: import com.tomsawyer.editor.TSEColor; //import com.tomsawyer.util.TSConstPoint;
051: import com.tomsawyer.drawing.geometry.TSConstPoint;
052: import com.tomsawyer.editor.graphics.TSEGraphics; //import com.tomsawyer.util.TSTransform;
053: import com.tomsawyer.editor.TSTransform;
054:
055: public abstract class ETArrowHead implements IETArrowHead {
056:
057: /**
058: * Protectect constructor, this class is abstract.
059: */
060: protected ETArrowHead(int nKind) {
061: super ();
062: kind = nKind;
063: }
064:
065: /* (non-Javadoc)
066: * Please note you must have color selected in the Graphics object, the color param is used to fill interior regions.
067: */
068: public boolean draw(IDrawInfo pInfo, TSConstPoint fromPt,
069: TSConstPoint toPt, TSEColor color) {
070: Shape shape = getShape(pInfo, fromPt, toPt);
071: if (shape == null)
072: return false;
073:
074: boolean didDraw;
075: AffineTransform rotationTransform = getRotationTransform(pInfo,
076: fromPt, toPt);
077:
078: TSEGraphics dc = pInfo.getTSEGraphics();
079: AffineTransform prevTransform;
080:
081: if (rotationTransform != null) {
082: // Save the current transform
083: prevTransform = dc.getTransform();
084: dc.setTransform(rotationTransform);
085: } else
086: prevTransform = null;
087:
088: if (shape != null) {
089: if (isFilled() || isOpenRegion() == false) {
090: Color prevColor = dc.getColor();
091: dc.setColor(color);
092: dc.fill(shape);
093: dc.setColor(prevColor);
094: }
095: dc.draw(shape);
096: didDraw = true;
097: } else
098: didDraw = false;
099:
100: // restore the transform
101: if (rotationTransform != null)
102: dc.setTransform(prevTransform);
103:
104: return didDraw;
105: }
106:
107: /* (non-Javadoc)
108: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#getKind()
109: */
110: public int getKind() {
111: return kind;
112: }
113:
114: /* (non-Javadoc)
115: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#setHeight(int)
116: */
117: public void setHeight(int height) {
118: this .m_height = height;
119: }
120:
121: /* (non-Javadoc)
122: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#setWidth(int)
123: */
124: public void setWidth(int width) {
125: this .m_width = width;
126: }
127:
128: /* (non-Javadoc)
129: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#getHeight()
130: */
131: public int getHeight() {
132: return m_height == 0 ? getDefaultHeight() : m_height;
133: }
134:
135: /* (non-Javadoc)
136: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#getWidth()
137: */
138: public int getWidth() {
139: return m_width == 0 ? getDefaultWidth() : m_width;
140: }
141:
142: /* (non-Javadoc)
143: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#getDefaultHeight()
144: */
145: public int getDefaultHeight() {
146: return 10; // Just a guess.
147: }
148:
149: /* (non-Javadoc)
150: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead#getDefaultWidth()
151: */
152: public int getDefaultWidth() {
153: return 8; // Just a guess.
154: }
155:
156: /*
157: * return true if your closed and filled.
158: */
159: protected boolean isFilled() {
160: return isOpenRegion() == false;
161: }
162:
163: /*
164: * return true if you don't closed region.
165: */
166: protected abstract boolean isOpenRegion();
167:
168: // Derived classes must determine their shape.
169: public abstract Shape getShape(IDrawInfo pInfo,
170: TSConstPoint fromPt, TSConstPoint toPt);
171:
172: /*
173: * Some arrow heads mgiht require rotation to drawn with respect to the line seqment direction.
174: */
175: protected boolean requiresRotation() {
176: return false;
177: }
178:
179: protected AffineTransform getRotationTransform(IDrawInfo pInfo,
180: TSConstPoint fromPt, TSConstPoint toPt) {
181: if (requiresRotation()) {
182: TSTransform transform = pInfo.getTSTransform();
183: double rotateX = (double) transform.xToDevice((double) toPt
184: .getX());
185: double rotateY = (double) transform.yToDevice((double) toPt
186: .getY());
187: return pInfo.getTSEGraphics().getTransform()
188: .getRotateInstance(getTheta(fromPt, toPt), rotateX,
189: rotateY);
190: }
191: return null;
192: }
193:
194: /**
195: * Calculates the angle of a line in radians defined by points 1 and 2, with
196: * point 1 at the origin. The atan function alone is not sufficient because
197: * it only returns values in the range of -pi/2 < theta < pi/2.
198: */
199: public static double getTheta(double x1, double x2, double y1,
200: double y2) {
201: double theta = 0.0f;
202: double pi = (double) Math.PI;
203:
204: if (x2 == x1) // Can't div by zero.
205: {
206: if (y2 > y1)
207: theta = pi / 2.0f;
208: if (y2 < y1)
209: theta = 3.0f * pi / 2.0f;
210: } else {
211: double slope = (y2 - y1) / (x2 - x1);
212: theta = (float) Math.atan(slope);
213: // if point 2 is to the left of point1, then it's in the 2nd or 3rd quadrants
214: // and must add pi radians to angle
215: if (x2 < x1)
216: theta += pi;
217: }
218: return theta;
219: }
220:
221: /*
222: * the angle of rotation in radians
223: */
224: protected double getTheta(TSConstPoint fromPt, TSConstPoint toPt) {
225: return getTheta(fromPt.getX(), toPt.getX(), fromPt.getY(), toPt
226: .getY());
227: }
228:
229: protected int m_width = 0;
230: protected int m_height = 0;
231: protected int kind;
232: }
|