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 }