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 }