001: /* ===========================================================
002: * JFreeChart : a free chart library for the Java(tm) platform
003: * ===========================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jfreechart/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * -------------------
028: * MarkerAxisBand.java
029: * -------------------
030: * (C) Copyright 2000-2005, by Object Refinery Limited.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): -;
034: *
035: * $Id: MarkerAxisBand.java,v 1.6.2.1 2005/10/25 20:37:34 mungady Exp $
036: *
037: * Changes (from 03-Sep-2002)
038: * --------------------------
039: * 03-Sep-2002 : Updated Javadoc comments (DG);
040: * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
041: * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG);
042: * 26-Mar-2003 : Implemented Serializable (DG);
043: * 13-May-2003 : Renamed HorizontalMarkerAxisBand --> MarkerAxisBand (DG);
044: * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG);
045: * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
046: * 07-Apr-2004 : Changed text bounds calculation (DG);
047: *
048: */
049:
050: package org.jfree.chart.axis;
051:
052: import java.awt.AlphaComposite;
053: import java.awt.Color;
054: import java.awt.Composite;
055: import java.awt.Font;
056: import java.awt.FontMetrics;
057: import java.awt.Graphics2D;
058: import java.awt.font.LineMetrics;
059: import java.awt.geom.Rectangle2D;
060: import java.io.Serializable;
061: import java.util.Iterator;
062: import java.util.List;
063:
064: import org.jfree.chart.plot.IntervalMarker;
065: import org.jfree.text.TextUtilities;
066: import org.jfree.ui.RectangleEdge;
067: import org.jfree.util.ObjectUtilities;
068:
069: /**
070: * A band that can be added to a number axis to display regions.
071: */
072: public class MarkerAxisBand implements Serializable {
073:
074: /** For serialization. */
075: private static final long serialVersionUID = -1729482413886398919L;
076:
077: /** The axis that the band belongs to. */
078: private NumberAxis axis;
079:
080: /** The top outer gap. */
081: private double topOuterGap;
082:
083: /** The top inner gap. */
084: private double topInnerGap;
085:
086: /** The bottom outer gap. */
087: private double bottomOuterGap;
088:
089: /** The bottom inner gap. */
090: private double bottomInnerGap;
091:
092: /** The font. */
093: private Font font;
094:
095: /** Storage for the markers. */
096: private List markers;
097:
098: /**
099: * Constructs a new axis band.
100: *
101: * @param axis the owner.
102: * @param topOuterGap the top outer gap.
103: * @param topInnerGap the top inner gap.
104: * @param bottomOuterGap the bottom outer gap.
105: * @param bottomInnerGap the bottom inner gap.
106: * @param font the font.
107: */
108: public MarkerAxisBand(NumberAxis axis, double topOuterGap,
109: double topInnerGap, double bottomOuterGap,
110: double bottomInnerGap, Font font) {
111: this .axis = axis;
112: this .topOuterGap = topOuterGap;
113: this .topInnerGap = topInnerGap;
114: this .bottomOuterGap = bottomOuterGap;
115: this .bottomInnerGap = bottomInnerGap;
116: this .font = font;
117: this .markers = new java.util.ArrayList();
118: }
119:
120: /**
121: * Adds a marker to the band.
122: *
123: * @param marker the marker.
124: */
125: public void addMarker(IntervalMarker marker) {
126: this .markers.add(marker);
127: }
128:
129: /**
130: * Returns the height of the band.
131: *
132: * @param g2 the graphics device.
133: *
134: * @return The height of the band.
135: */
136: public double getHeight(Graphics2D g2) {
137:
138: double result = 0.0;
139: if (this .markers.size() > 0) {
140: LineMetrics metrics = this .font.getLineMetrics("123g", g2
141: .getFontRenderContext());
142: result = this .topOuterGap + this .topInnerGap
143: + metrics.getHeight() + this .bottomInnerGap
144: + this .bottomOuterGap;
145: }
146: return result;
147:
148: }
149:
150: /**
151: * A utility method that draws a string inside a rectangle.
152: *
153: * @param g2 the graphics device.
154: * @param bounds the rectangle.
155: * @param font the font.
156: * @param text the text.
157: */
158: private void drawStringInRect(Graphics2D g2, Rectangle2D bounds,
159: Font font, String text) {
160:
161: g2.setFont(font);
162: FontMetrics fm = g2.getFontMetrics(font);
163: Rectangle2D r = TextUtilities.getTextBounds(text, g2, fm);
164: double x = bounds.getX();
165: if (r.getWidth() < bounds.getWidth()) {
166: x = x + (bounds.getWidth() - r.getWidth()) / 2;
167: }
168: LineMetrics metrics = font.getLineMetrics(text, g2
169: .getFontRenderContext());
170: g2.drawString(text, (float) x, (float) (bounds.getMaxY()
171: - this .bottomInnerGap - metrics.getDescent()));
172: }
173:
174: /**
175: * Draws the band.
176: *
177: * @param g2 the graphics device.
178: * @param plotArea the plot area.
179: * @param dataArea the data area.
180: * @param x the x-coordinate.
181: * @param y the y-coordinate.
182: */
183: public void draw(Graphics2D g2, Rectangle2D plotArea,
184: Rectangle2D dataArea, double x, double y) {
185:
186: double h = getHeight(g2);
187: Iterator iterator = this .markers.iterator();
188: while (iterator.hasNext()) {
189: IntervalMarker marker = (IntervalMarker) iterator.next();
190: double start = Math.max(marker.getStartValue(), this .axis
191: .getRange().getLowerBound());
192: double end = Math.min(marker.getEndValue(), this .axis
193: .getRange().getUpperBound());
194: double s = this .axis.valueToJava2D(start, dataArea,
195: RectangleEdge.BOTTOM);
196: double e = this .axis.valueToJava2D(end, dataArea,
197: RectangleEdge.BOTTOM);
198: Rectangle2D r = new Rectangle2D.Double(s, y
199: + this .topOuterGap, e - s, h - this .topOuterGap
200: - this .bottomOuterGap);
201:
202: Composite originalComposite = g2.getComposite();
203: g2.setComposite(AlphaComposite.getInstance(
204: AlphaComposite.SRC_OVER, marker.getAlpha()));
205: g2.setPaint(marker.getPaint());
206: g2.fill(r);
207: g2.setPaint(marker.getOutlinePaint());
208: g2.draw(r);
209: g2.setComposite(originalComposite);
210:
211: g2.setPaint(Color.black);
212: drawStringInRect(g2, r, this .font, marker.getLabel());
213: }
214:
215: }
216:
217: /**
218: * Tests this axis for equality with another object. Note that the axis
219: * that the band belongs to is ignored in the test.
220: *
221: * @param obj the object (<code>null</code> permitted).
222: *
223: * @return <code>true</code> or <code>false</code>.
224: */
225: public boolean equals(Object obj) {
226: if (obj == this ) {
227: return true;
228: }
229: if (!(obj instanceof MarkerAxisBand)) {
230: return false;
231: }
232: MarkerAxisBand that = (MarkerAxisBand) obj;
233: if (this .topOuterGap != that.topOuterGap) {
234: return false;
235: }
236: if (this .topInnerGap != that.topInnerGap) {
237: return false;
238: }
239: if (this .bottomInnerGap != that.bottomInnerGap) {
240: return false;
241: }
242: if (this .bottomOuterGap != that.bottomOuterGap) {
243: return false;
244: }
245: if (!ObjectUtilities.equal(this .font, that.font)) {
246: return false;
247: }
248: if (!ObjectUtilities.equal(this .markers, that.markers)) {
249: return false;
250: }
251: return true;
252: }
253:
254: /**
255: * Returns a hash code for the object.
256: *
257: * @return A hash code.
258: */
259: public int hashCode() {
260: int result = 37;
261: result = 19 * result + this .font.hashCode();
262: result = 19 * result + this.markers.hashCode();
263: return result;
264: }
265:
266: }
|