001: /**
002: * Chart2D, a java library for drawing two dimensional charts.
003: * Copyright (C) 2001 Jason J. Simas
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * The author of this library may be contacted at:
019: * E-mail: jjsimas@users.sourceforge.net
020: * Street Address: J J Simas, 887 Tico Road, Ojai, CA 93023-3555 USA
021: */package net.sourceforge.chart2d;
022:
023: import java.awt.*;
024: import java.awt.geom.*;
025: import java.util.*;
026:
027: /**
028: * A line capable of gradient paint and warning region coloring.
029: */
030: final class FancyLine extends FancyShape {
031:
032: private GeneralPath line;
033: private BasicStroke stroke;
034: private BasicStroke outlineStroke;
035: private float thickness;
036: private boolean fillArea;
037: private Rectangle2D.Float clipBounds;
038: private FancyLine[] warningLines;
039: private boolean needsUpdate;
040:
041: /**
042: * Creates a default FancyLine object.
043: */
044: FancyLine() {
045: needsUpdate = true;
046: line = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
047: }
048:
049: /**
050: * Sets the thickness of this line.
051: * @param t The line thickness.
052: */
053: final void setThickness(float t) {
054: thickness = t;
055: needsUpdate = true;
056: }
057:
058: /**
059: * Sets whether the bounds of this line intersected with the graph bounds will be filled.
060: * @param f If true, then filled.
061: */
062: final void setFillArea(boolean f) {
063: fillArea = f;
064: }
065:
066: /**
067: * Sets the general path of this line.
068: * @param l The general path.
069: */
070: final void setLine(GeneralPath l) {
071: needsUpdate = true;
072: line = l;
073: }
074:
075: /**
076: * Sets the clipping bounds (specifying which parts of the line to paint).
077: * @param b The clipping bounds.
078: */
079: final void setClipBounds(Rectangle2D.Float b) {
080: needsUpdate = true;
081: clipBounds = b;
082: }
083:
084: /**
085: * Gets the thickness of this line.
086: * return The line thickness.
087: */
088: final float getThickness() {
089: return thickness;
090: }
091:
092: /**
093: * Gets whether the bounds of this line intersected with the graph bounds will be filled.
094: * @return If true, then filled.
095: */
096: final boolean getFillArea() {
097: return fillArea;
098: }
099:
100: /**
101: * Gets the general path of this line.
102: * @return The general path.
103: */
104: final GeneralPath getLine() {
105: return line;
106: }
107:
108: /**
109: * Gets the clipping bounds (specifying which parts of the line to paint).
110: * @return The clipping bounds.
111: */
112: final Rectangle2D.Float getClipBounds() {
113: return clipBounds;
114: }
115:
116: /**
117: * Paints the line on the Graphics2D object after calling update.
118: * @param g2D The Graphics2D object.
119: */
120: final void paint(Graphics2D g2D) {
121:
122: update();
123:
124: Stroke oldStroke = g2D.getStroke();
125: Paint oldPaint = g2D.getPaint();
126: Shape oldClip = g2D.getClip();
127:
128: java.awt.geom.Area clipArea = new java.awt.geom.Area(clipBounds);
129: clipArea.intersect(new java.awt.geom.Area(oldClip));
130: g2D.setClip(clipArea);
131:
132: if (getOutlineExistence() && thickness > 2f) {
133: g2D.setStroke(outlineStroke);
134: g2D.setPaint(getOutlinePaint());
135: g2D.draw(line);
136: }
137:
138: g2D.setPaint(getPaint());
139: g2D.setStroke(stroke);
140: if (fillArea)
141: g2D.fill(line);
142: else
143: g2D.draw(line);
144:
145: g2D.setPaint(oldPaint);
146: g2D.setClip(oldClip);
147: g2D.setStroke(oldStroke);
148:
149: if (warningLines != null) {
150: for (int i = 0; i < warningLines.length; ++i)
151: warningLines[i].paint(g2D);
152: }
153: }
154:
155: /**
156: * Updates the FancyLine.
157: */
158: final void update() {
159:
160: super .update();
161:
162: if (needsUpdate) {
163:
164: outlineStroke = new BasicStroke((float) thickness,
165: BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
166: 10.0f, Area.CONTINUOUS, 0.0f);
167: float tempThickness = thickness > 2f
168: && getOutlineExistence() ? thickness - 2f
169: : thickness;
170: stroke = new BasicStroke((float) tempThickness,
171: BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
172: 10.0f, Area.CONTINUOUS, 0.0f);
173:
174: if (getWarningRegions() != null) {
175:
176: warningLines = new FancyLine[getWarningRegions().size()];
177: for (int i = 0; i < warningLines.length; ++i) {
178:
179: FancyLine warningLine = new FancyLine();
180:
181: WarningRegion warningRegion = (WarningRegion) getWarningRegions()
182: .get(i);
183: java.awt.geom.Area clipArea = new java.awt.geom.Area(
184: clipBounds);
185: java.awt.geom.Area wrArea = new java.awt.geom.Area(
186: warningRegion.getBackgroundBounds());
187: clipArea.intersect(wrArea);
188: Rectangle2D.Float wrClipBounds = new Rectangle2D.Float();
189: wrClipBounds.setRect(clipArea.getBounds2D());
190: warningLine.setClipBounds(wrClipBounds);
191: warningLine.setFillArea(getFillArea());
192: warningLine.setThickness(getThickness());
193: warningLine.setColor(warningRegion
194: .getComponentColor());
195: warningLine.setLightBounds(getLightBounds());
196: warningLine.setLightSource(getLightSource());
197: warningLine.setOutlineColor(getOutlineColor());
198: warningLine
199: .setOutlineExistence(getOutlineExistence());
200: warningLine.setType(getType());
201: warningLine.setWarningRegions(null);
202: warningLine.setLine(line);
203: warningLines[i] = warningLine;
204: }
205: }
206: needsUpdate = false;
207: }
208: }
209: }
|