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