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 }