001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, 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 * PeriodAxisLabelInfo.java
029 * ------------------------
030 * (C) Copyright 2004-2007, by Object Refinery Limited and Contributors.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * Changes
036 * -------
037 * 01-Jun-2004 : Version 1 (DG);
038 * 23-Feb-2005 : Replaced Spacer with RectangleInsets (DG);
039 * 01-Mar-2005 : Modified constructors to accept DateFormat (DG);
040 * 20-May-2005 : Added default constants and null argument checks in the
041 * constructor (DG);
042 *
043 */
044
045 package org.jfree.chart.axis;
046
047 import java.awt.BasicStroke;
048 import java.awt.Color;
049 import java.awt.Font;
050 import java.awt.Paint;
051 import java.awt.Stroke;
052 import java.io.IOException;
053 import java.io.ObjectInputStream;
054 import java.io.ObjectOutputStream;
055 import java.io.Serializable;
056 import java.lang.reflect.Constructor;
057 import java.text.DateFormat;
058 import java.util.Date;
059 import java.util.TimeZone;
060
061 import org.jfree.data.time.RegularTimePeriod;
062 import org.jfree.io.SerialUtilities;
063 import org.jfree.ui.RectangleInsets;
064
065 /**
066 * A record that contains information for one "band" of date labels in
067 * a {@link PeriodAxis}.
068 */
069 public class PeriodAxisLabelInfo implements Cloneable, Serializable {
070
071 // TODO: this class is mostly immutable, so implementing Cloneable isn't
072 // really necessary. But there is still a hole in that you can get the
073 // dateFormat and modify it. We could return a copy, but that would slow
074 // things down. Needs resolving.
075
076 /** For serialization. */
077 private static final long serialVersionUID = 5710451740920277357L;
078
079 /** The default insets. */
080 public static final RectangleInsets DEFAULT_INSETS
081 = new RectangleInsets(2, 2, 2, 2);
082
083 /** The default font. */
084 public static final Font DEFAULT_FONT
085 = new Font("SansSerif", Font.PLAIN, 10);
086
087 /** The default label paint. */
088 public static final Paint DEFAULT_LABEL_PAINT = Color.black;
089
090 /** The default divider stroke. */
091 public static final Stroke DEFAULT_DIVIDER_STROKE = new BasicStroke(0.5f);
092
093 /** The default divider paint. */
094 public static final Paint DEFAULT_DIVIDER_PAINT = Color.gray;
095
096 /** The subclass of {@link RegularTimePeriod} to use for this band. */
097 private Class periodClass;
098
099 /** Controls the gaps around the band. */
100 private RectangleInsets padding;
101
102 /** The date formatter. */
103 private DateFormat dateFormat;
104
105 /** The label font. */
106 private Font labelFont;
107
108 /** The label paint. */
109 private transient Paint labelPaint;
110
111 /** A flag that controls whether or not dividers are visible. */
112 private boolean drawDividers;
113
114 /** The stroke used to draw the dividers. */
115 private transient Stroke dividerStroke;
116
117 /** The paint used to draw the dividers. */
118 private transient Paint dividerPaint;
119
120 /**
121 * Creates a new instance.
122 *
123 * @param periodClass the subclass of {@link RegularTimePeriod} to use
124 * (<code>null</code> not permitted).
125 * @param dateFormat the date format (<code>null</code> not permitted).
126 */
127 public PeriodAxisLabelInfo(Class periodClass, DateFormat dateFormat) {
128 this(
129 periodClass, dateFormat, DEFAULT_INSETS, DEFAULT_FONT,
130 DEFAULT_LABEL_PAINT, true, DEFAULT_DIVIDER_STROKE,
131 DEFAULT_DIVIDER_PAINT
132 );
133 }
134
135 /**
136 * Creates a new instance.
137 *
138 * @param periodClass the subclass of {@link RegularTimePeriod} to use
139 * (<code>null</code> not permitted).
140 * @param dateFormat the date format (<code>null</code> not permitted).
141 * @param padding controls the space around the band (<code>null</code>
142 * not permitted).
143 * @param labelFont the label font (<code>null</code> not permitted).
144 * @param labelPaint the label paint (<code>null</code> not permitted).
145 * @param drawDividers a flag that controls whether dividers are drawn.
146 * @param dividerStroke the stroke used to draw the dividers
147 * (<code>null</code> not permitted).
148 * @param dividerPaint the paint used to draw the dividers
149 * (<code>null</code> not permitted).
150 */
151 public PeriodAxisLabelInfo(Class periodClass, DateFormat dateFormat,
152 RectangleInsets padding,
153 Font labelFont, Paint labelPaint,
154 boolean drawDividers, Stroke dividerStroke,
155 Paint dividerPaint) {
156 if (periodClass == null) {
157 throw new IllegalArgumentException("Null 'periodClass' argument.");
158 }
159 if (dateFormat == null) {
160 throw new IllegalArgumentException("Null 'dateFormat' argument.");
161 }
162 if (padding == null) {
163 throw new IllegalArgumentException("Null 'padding' argument.");
164 }
165 if (labelFont == null) {
166 throw new IllegalArgumentException("Null 'labelFont' argument.");
167 }
168 if (labelPaint == null) {
169 throw new IllegalArgumentException("Null 'labelPaint' argument.");
170 }
171 if (dividerStroke == null) {
172 throw new IllegalArgumentException(
173 "Null 'dividerStroke' argument.");
174 }
175 if (dividerPaint == null) {
176 throw new IllegalArgumentException("Null 'dividerPaint' argument.");
177 }
178 this.periodClass = periodClass;
179 this.dateFormat = dateFormat;
180 this.padding = padding;
181 this.labelFont = labelFont;
182 this.labelPaint = labelPaint;
183 this.drawDividers = drawDividers;
184 this.dividerStroke = dividerStroke;
185 this.dividerPaint = dividerPaint;
186 }
187
188 /**
189 * Returns the subclass of {@link RegularTimePeriod} that should be used
190 * to generate the date labels.
191 *
192 * @return The class.
193 */
194 public Class getPeriodClass() {
195 return this.periodClass;
196 }
197
198 /**
199 * Returns the date formatter.
200 *
201 * @return The date formatter (never <code>null</code>).
202 */
203 public DateFormat getDateFormat() {
204 return this.dateFormat;
205 }
206
207 /**
208 * Returns the padding for the band.
209 *
210 * @return The padding.
211 */
212 public RectangleInsets getPadding() {
213 return this.padding;
214 }
215
216 /**
217 * Returns the label font.
218 *
219 * @return The label font (never <code>null</code>).
220 */
221 public Font getLabelFont() {
222 return this.labelFont;
223 }
224
225 /**
226 * Returns the label paint.
227 *
228 * @return The label paint.
229 */
230 public Paint getLabelPaint() {
231 return this.labelPaint;
232 }
233
234 /**
235 * Returns a flag that controls whether or not dividers are drawn.
236 *
237 * @return A flag.
238 */
239 public boolean getDrawDividers() {
240 return this.drawDividers;
241 }
242
243 /**
244 * Returns the stroke used to draw the dividers.
245 *
246 * @return The stroke.
247 */
248 public Stroke getDividerStroke() {
249 return this.dividerStroke;
250 }
251
252 /**
253 * Returns the paint used to draw the dividers.
254 *
255 * @return The paint.
256 */
257 public Paint getDividerPaint() {
258 return this.dividerPaint;
259 }
260
261 /**
262 * Creates a time period that includes the specified millisecond, assuming
263 * the given time zone.
264 *
265 * @param millisecond the time.
266 * @param zone the time zone.
267 *
268 * @return The time period.
269 */
270 public RegularTimePeriod createInstance(Date millisecond, TimeZone zone) {
271 RegularTimePeriod result = null;
272 try {
273 Constructor c = this.periodClass.getDeclaredConstructor(
274 new Class[] {Date.class, TimeZone.class}
275 );
276 result = (RegularTimePeriod) c.newInstance(
277 new Object[] {millisecond, zone}
278 );
279 }
280 catch (Exception e) {
281 // do nothing
282 }
283 return result;
284 }
285
286 /**
287 * Tests this object for equality with an arbitrary object.
288 *
289 * @param obj the object to test against (<code>null</code> permitted).
290 *
291 * @return A boolean.
292 */
293 public boolean equals(Object obj) {
294 if (obj == this) {
295 return true;
296 }
297 if (obj instanceof PeriodAxisLabelInfo) {
298 PeriodAxisLabelInfo info = (PeriodAxisLabelInfo) obj;
299 if (!info.periodClass.equals(this.periodClass)) {
300 return false;
301 }
302 if (!info.dateFormat.equals(this.dateFormat)) {
303 return false;
304 }
305 if (!info.padding.equals(this.padding)) {
306 return false;
307 }
308 if (!info.labelFont.equals(this.labelFont)) {
309 return false;
310 }
311 if (!info.labelPaint.equals(this.labelPaint)) {
312 return false;
313 }
314 if (info.drawDividers != this.drawDividers) {
315 return false;
316 }
317 if (!info.dividerStroke.equals(this.dividerStroke)) {
318 return false;
319 }
320 if (!info.dividerPaint.equals(this.dividerPaint)) {
321 return false;
322 }
323 return true;
324 }
325 return false;
326 }
327
328 /**
329 * Returns a hash code for this object.
330 *
331 * @return A hash code.
332 */
333 public int hashCode() {
334 int result = 41;
335 result = 37 * this.periodClass.hashCode();
336 result = 37 * this.dateFormat.hashCode();
337 return result;
338 }
339
340 /**
341 * Returns a clone of the object.
342 *
343 * @return A clone.
344 *
345 * @throws CloneNotSupportedException if cloning is not supported.
346 */
347 public Object clone() throws CloneNotSupportedException {
348 PeriodAxisLabelInfo clone = (PeriodAxisLabelInfo) super.clone();
349 return clone;
350 }
351
352 /**
353 * Provides serialization support.
354 *
355 * @param stream the output stream.
356 *
357 * @throws IOException if there is an I/O error.
358 */
359 private void writeObject(ObjectOutputStream stream) throws IOException {
360 stream.defaultWriteObject();
361 SerialUtilities.writePaint(this.labelPaint, stream);
362 SerialUtilities.writeStroke(this.dividerStroke, stream);
363 SerialUtilities.writePaint(this.dividerPaint, stream);
364 }
365
366 /**
367 * Provides serialization support.
368 *
369 * @param stream the input stream.
370 *
371 * @throws IOException if there is an I/O error.
372 * @throws ClassNotFoundException if there is a classpath problem.
373 */
374 private void readObject(ObjectInputStream stream)
375 throws IOException, ClassNotFoundException {
376 stream.defaultReadObject();
377 this.labelPaint = SerialUtilities.readPaint(stream);
378 this.dividerStroke = SerialUtilities.readStroke(stream);
379 this.dividerPaint = SerialUtilities.readPaint(stream);
380 }
381
382 }