001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, 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-2008, 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 result = (RegularTimePeriod) c.newInstance(new Object[] {
276 millisecond, zone});
277 }
278 catch (Exception e) {
279 // do nothing
280 }
281 return result;
282 }
283
284 /**
285 * Tests this object for equality with an arbitrary object.
286 *
287 * @param obj the object to test against (<code>null</code> permitted).
288 *
289 * @return A boolean.
290 */
291 public boolean equals(Object obj) {
292 if (obj == this) {
293 return true;
294 }
295 if (obj instanceof PeriodAxisLabelInfo) {
296 PeriodAxisLabelInfo info = (PeriodAxisLabelInfo) obj;
297 if (!info.periodClass.equals(this.periodClass)) {
298 return false;
299 }
300 if (!info.dateFormat.equals(this.dateFormat)) {
301 return false;
302 }
303 if (!info.padding.equals(this.padding)) {
304 return false;
305 }
306 if (!info.labelFont.equals(this.labelFont)) {
307 return false;
308 }
309 if (!info.labelPaint.equals(this.labelPaint)) {
310 return false;
311 }
312 if (info.drawDividers != this.drawDividers) {
313 return false;
314 }
315 if (!info.dividerStroke.equals(this.dividerStroke)) {
316 return false;
317 }
318 if (!info.dividerPaint.equals(this.dividerPaint)) {
319 return false;
320 }
321 return true;
322 }
323 return false;
324 }
325
326 /**
327 * Returns a hash code for this object.
328 *
329 * @return A hash code.
330 */
331 public int hashCode() {
332 int result = 41;
333 result = 37 * this.periodClass.hashCode();
334 result = 37 * this.dateFormat.hashCode();
335 return result;
336 }
337
338 /**
339 * Returns a clone of the object.
340 *
341 * @return A clone.
342 *
343 * @throws CloneNotSupportedException if cloning is not supported.
344 */
345 public Object clone() throws CloneNotSupportedException {
346 PeriodAxisLabelInfo clone = (PeriodAxisLabelInfo) super.clone();
347 return clone;
348 }
349
350 /**
351 * Provides serialization support.
352 *
353 * @param stream the output stream.
354 *
355 * @throws IOException if there is an I/O error.
356 */
357 private void writeObject(ObjectOutputStream stream) throws IOException {
358 stream.defaultWriteObject();
359 SerialUtilities.writePaint(this.labelPaint, stream);
360 SerialUtilities.writeStroke(this.dividerStroke, stream);
361 SerialUtilities.writePaint(this.dividerPaint, stream);
362 }
363
364 /**
365 * Provides serialization support.
366 *
367 * @param stream the input stream.
368 *
369 * @throws IOException if there is an I/O error.
370 * @throws ClassNotFoundException if there is a classpath problem.
371 */
372 private void readObject(ObjectInputStream stream)
373 throws IOException, ClassNotFoundException {
374 stream.defaultReadObject();
375 this.labelPaint = SerialUtilities.readPaint(stream);
376 this.dividerStroke = SerialUtilities.readStroke(stream);
377 this.dividerPaint = SerialUtilities.readPaint(stream);
378 }
379
380 }