001: /* ===========================================================
002: * JFreeChart : a free chart library for the Java(tm) platform
003: * ===========================================================
004: *
005: * (C) Copyright 2000-2006, 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: * AbstractCategoryItemLabelGenerator.java
029: * ---------------------------------------
030: * (C) Copyright 2005, 2006, by Object Refinery Limited.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): -;
034: *
035: * $Id: AbstractCategoryItemLabelGenerator.java,v 1.6.2.2 2006/05/03 15:44:02 mungady Exp $
036: *
037: * Changes
038: * -------
039: * 11-May-2004 : Version 1, distilled from StandardCategoryLabelGenerator (DG);
040: * 31-Jan-2005 : Added methods to return row and column labels (DG);
041: * 17-May-2005 : Added percentage to item array (DG);
042: * ------------- JFREECHART 1.0.0 ---------------------------------------------
043: * 03-May-2006 : Added new constructor (DG);
044: */
045:
046: package org.jfree.chart.labels;
047:
048: import java.io.Serializable;
049: import java.text.DateFormat;
050: import java.text.MessageFormat;
051: import java.text.NumberFormat;
052:
053: import org.jfree.data.DataUtilities;
054: import org.jfree.data.category.CategoryDataset;
055: import org.jfree.util.ObjectUtilities;
056: import org.jfree.util.PublicCloneable;
057:
058: /**
059: * A base class that can be used to create a label or tooltip generator that
060: * can be assigned to a
061: * {@link org.jfree.chart.renderer.category.CategoryItemRenderer}.
062: */
063: public abstract class AbstractCategoryItemLabelGenerator implements
064: PublicCloneable, Cloneable, Serializable {
065:
066: /** For serialization. */
067: private static final long serialVersionUID = -7108591260223293197L;
068:
069: /**
070: * The label format string used by a <code>MessageFormat</code> object to
071: * combine the standard items: {0} = series name, {1} = category,
072: * {2} = value, {3} = value as a percentage of the column total.
073: */
074: private String labelFormat;
075:
076: /** The string used to represent a null value. */
077: private String nullValueString;
078:
079: /**
080: * A number formatter used to preformat the value before it is passed to
081: * the MessageFormat object.
082: */
083: private NumberFormat numberFormat;
084:
085: /**
086: * A date formatter used to preformat the value before it is passed to the
087: * MessageFormat object.
088: */
089: private DateFormat dateFormat;
090:
091: /**
092: * A number formatter used to preformat the percentage value before it is
093: * passed to the MessageFormat object.
094: */
095: private NumberFormat percentFormat;
096:
097: /**
098: * Creates a label generator with the specified number formatter.
099: *
100: * @param labelFormat the label format string (<code>null</code> not
101: * permitted).
102: * @param formatter the number formatter (<code>null</code> not permitted).
103: */
104: protected AbstractCategoryItemLabelGenerator(String labelFormat,
105: NumberFormat formatter) {
106: this (labelFormat, formatter, NumberFormat.getPercentInstance());
107: }
108:
109: /**
110: * Creates a label generator with the specified number formatter.
111: *
112: * @param labelFormat the label format string (<code>null</code> not
113: * permitted).
114: * @param formatter the number formatter (<code>null</code> not permitted).
115: * @param percentFormatter the percent formatter (<code>null</code> not
116: * permitted).
117: *
118: * @since 1.0.2
119: */
120: protected AbstractCategoryItemLabelGenerator(String labelFormat,
121: NumberFormat formatter, NumberFormat percentFormatter) {
122: if (labelFormat == null) {
123: throw new IllegalArgumentException(
124: "Null 'labelFormat' argument.");
125: }
126: if (formatter == null) {
127: throw new IllegalArgumentException(
128: "Null 'formatter' argument.");
129: }
130: if (percentFormatter == null) {
131: throw new IllegalArgumentException(
132: "Null 'percentFormatter' argument.");
133: }
134: this .labelFormat = labelFormat;
135: this .numberFormat = formatter;
136: this .percentFormat = percentFormatter;
137: this .dateFormat = null;
138: this .nullValueString = "-";
139: }
140:
141: /**
142: * Creates a label generator with the specified date formatter.
143: *
144: * @param labelFormat the label format string (<code>null</code> not
145: * permitted).
146: * @param formatter the date formatter (<code>null</code> not permitted).
147: */
148: protected AbstractCategoryItemLabelGenerator(String labelFormat,
149: DateFormat formatter) {
150: if (labelFormat == null) {
151: throw new IllegalArgumentException(
152: "Null 'labelFormat' argument.");
153: }
154: if (formatter == null) {
155: throw new IllegalArgumentException(
156: "Null 'formatter' argument.");
157: }
158: this .labelFormat = labelFormat;
159: this .numberFormat = null;
160: this .percentFormat = NumberFormat.getPercentInstance();
161: this .dateFormat = formatter;
162: this .nullValueString = "-";
163: }
164:
165: /**
166: * Generates a label for the specified row.
167: *
168: * @param dataset the dataset (<code>null</code> not permitted).
169: * @param row the row index (zero-based).
170: *
171: * @return The label.
172: */
173: public String generateRowLabel(CategoryDataset dataset, int row) {
174: return dataset.getRowKey(row).toString();
175: }
176:
177: /**
178: * Generates a label for the specified row.
179: *
180: * @param dataset the dataset (<code>null</code> not permitted).
181: * @param column the column index (zero-based).
182: *
183: * @return The label.
184: */
185: public String generateColumnLabel(CategoryDataset dataset,
186: int column) {
187: return dataset.getColumnKey(column).toString();
188: }
189:
190: /**
191: * Returns the label format string.
192: *
193: * @return The label format string (never <code>null</code>).
194: */
195: public String getLabelFormat() {
196: return this .labelFormat;
197: }
198:
199: /**
200: * Returns the number formatter.
201: *
202: * @return The number formatter (possibly <code>null</code>).
203: */
204: public NumberFormat getNumberFormat() {
205: return this .numberFormat;
206: }
207:
208: /**
209: * Returns the date formatter.
210: *
211: * @return The date formatter (possibly <code>null</code>).
212: */
213: public DateFormat getDateFormat() {
214: return this .dateFormat;
215: }
216:
217: /**
218: * Generates a for the specified item.
219: *
220: * @param dataset the dataset (<code>null</code> not permitted).
221: * @param row the row index (zero-based).
222: * @param column the column index (zero-based).
223: *
224: * @return The label (possibly <code>null</code>).
225: */
226: protected String generateLabelString(CategoryDataset dataset,
227: int row, int column) {
228: if (dataset == null) {
229: throw new IllegalArgumentException(
230: "Null 'dataset' argument.");
231: }
232: String result = null;
233: Object[] items = createItemArray(dataset, row, column);
234: result = MessageFormat.format(this .labelFormat, items);
235: return result;
236:
237: }
238:
239: /**
240: * Creates the array of items that can be passed to the
241: * {@link MessageFormat} class for creating labels.
242: *
243: * @param dataset the dataset (<code>null</code> not permitted).
244: * @param row the row index (zero-based).
245: * @param column the column index (zero-based).
246: *
247: * @return The items (never <code>null</code>).
248: */
249: protected Object[] createItemArray(CategoryDataset dataset,
250: int row, int column) {
251: Object[] result = new Object[4];
252: result[0] = dataset.getRowKey(row).toString();
253: result[1] = dataset.getColumnKey(column).toString();
254: Number value = dataset.getValue(row, column);
255: if (value != null) {
256: if (this .numberFormat != null) {
257: result[2] = this .numberFormat.format(value);
258: } else if (this .dateFormat != null) {
259: result[2] = this .dateFormat.format(value);
260: }
261: } else {
262: result[2] = this .nullValueString;
263: }
264: if (value != null) {
265: double total = DataUtilities.calculateColumnTotal(dataset,
266: column);
267: double percent = value.doubleValue() / total;
268: result[3] = this .percentFormat.format(percent);
269: }
270:
271: return result;
272: }
273:
274: /**
275: * Tests this object for equality with an arbitrary object.
276: *
277: * @param obj the other object (<code>null</code> permitted).
278: *
279: * @return A boolean.
280: */
281: public boolean equals(Object obj) {
282: if (obj == this ) {
283: return true;
284: }
285: if (!(obj instanceof AbstractCategoryItemLabelGenerator)) {
286: return false;
287: }
288:
289: AbstractCategoryItemLabelGenerator that = (AbstractCategoryItemLabelGenerator) obj;
290: if (!this .labelFormat.equals(that.labelFormat)) {
291: return false;
292: }
293: if (!ObjectUtilities.equal(this .dateFormat, that.dateFormat)) {
294: return false;
295: }
296: if (!ObjectUtilities
297: .equal(this .numberFormat, that.numberFormat)) {
298: return false;
299: }
300: return true;
301: }
302:
303: /**
304: * Returns an independent copy of the generator.
305: *
306: * @return A clone.
307: *
308: * @throws CloneNotSupportedException should not happen.
309: */
310: public Object clone() throws CloneNotSupportedException {
311: AbstractCategoryItemLabelGenerator clone = (AbstractCategoryItemLabelGenerator) super
312: .clone();
313: if (this .numberFormat != null) {
314: clone.numberFormat = (NumberFormat) this .numberFormat
315: .clone();
316: }
317: if (this .dateFormat != null) {
318: clone.dateFormat = (DateFormat) this.dateFormat.clone();
319: }
320: return clone;
321: }
322:
323: }
|