001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2009, 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-2009, 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 * 02-Mar-2009 : Updated createInstance to use locale (DG); 043 * 044 */ 045 046 package org.jfree.chart.axis; 047 048 import java.awt.BasicStroke; 049 import java.awt.Color; 050 import java.awt.Font; 051 import java.awt.Paint; 052 import java.awt.Stroke; 053 import java.io.IOException; 054 import java.io.ObjectInputStream; 055 import java.io.ObjectOutputStream; 056 import java.io.Serializable; 057 import java.lang.reflect.Constructor; 058 import java.text.DateFormat; 059 import java.util.Date; 060 import java.util.Locale; 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( 175 "Null 'dividerStroke' argument."); 176 } 177 if (dividerPaint == null) { 178 throw new IllegalArgumentException("Null 'dividerPaint' argument."); 179 } 180 this.periodClass = periodClass; 181 this.dateFormat = dateFormat; 182 this.padding = padding; 183 this.labelFont = labelFont; 184 this.labelPaint = labelPaint; 185 this.drawDividers = drawDividers; 186 this.dividerStroke = dividerStroke; 187 this.dividerPaint = dividerPaint; 188 } 189 190 /** 191 * Returns the subclass of {@link RegularTimePeriod} that should be used 192 * to generate the date labels. 193 * 194 * @return The class. 195 */ 196 public Class getPeriodClass() { 197 return this.periodClass; 198 } 199 200 /** 201 * Returns the date formatter. 202 * 203 * @return The date formatter (never <code>null</code>). 204 */ 205 public DateFormat getDateFormat() { 206 return this.dateFormat; 207 } 208 209 /** 210 * Returns the padding for the band. 211 * 212 * @return The padding. 213 */ 214 public RectangleInsets getPadding() { 215 return this.padding; 216 } 217 218 /** 219 * Returns the label font. 220 * 221 * @return The label font (never <code>null</code>). 222 */ 223 public Font getLabelFont() { 224 return this.labelFont; 225 } 226 227 /** 228 * Returns the label paint. 229 * 230 * @return The label paint. 231 */ 232 public Paint getLabelPaint() { 233 return this.labelPaint; 234 } 235 236 /** 237 * Returns a flag that controls whether or not dividers are drawn. 238 * 239 * @return A flag. 240 */ 241 public boolean getDrawDividers() { 242 return this.drawDividers; 243 } 244 245 /** 246 * Returns the stroke used to draw the dividers. 247 * 248 * @return The stroke. 249 */ 250 public Stroke getDividerStroke() { 251 return this.dividerStroke; 252 } 253 254 /** 255 * Returns the paint used to draw the dividers. 256 * 257 * @return The paint. 258 */ 259 public Paint getDividerPaint() { 260 return this.dividerPaint; 261 } 262 263 /** 264 * Creates a time period that includes the specified millisecond, assuming 265 * the given time zone. 266 * 267 * @param millisecond the time. 268 * @param zone the time zone. 269 * 270 * @return The time period. 271 * 272 * @deprecated As of 1.0.13, use the method that specifies the locale also. 273 */ 274 public RegularTimePeriod createInstance(Date millisecond, TimeZone zone) { 275 return createInstance(millisecond, zone, Locale.getDefault()); 276 } 277 278 /** 279 * Creates a time period that includes the specified millisecond, assuming 280 * the given time zone. 281 * 282 * @param millisecond the time. 283 * @param zone the time zone. 284 * @param locale the locale. 285 * 286 * @return The time period. 287 * 288 * @since 1.0.13. 289 */ 290 public RegularTimePeriod createInstance(Date millisecond, TimeZone zone, 291 Locale locale) { 292 RegularTimePeriod result = null; 293 try { 294 Constructor c = this.periodClass.getDeclaredConstructor( 295 new Class[] {Date.class, TimeZone.class, Locale.class}); 296 result = (RegularTimePeriod) c.newInstance(new Object[] { 297 millisecond, zone, locale}); 298 } 299 catch (Exception e) { 300 // do nothing 301 } 302 return result; 303 } 304 305 /** 306 * Tests this object for equality with an arbitrary object. 307 * 308 * @param obj the object to test against (<code>null</code> permitted). 309 * 310 * @return A boolean. 311 */ 312 public boolean equals(Object obj) { 313 if (obj == this) { 314 return true; 315 } 316 if (obj instanceof PeriodAxisLabelInfo) { 317 PeriodAxisLabelInfo info = (PeriodAxisLabelInfo) obj; 318 if (!info.periodClass.equals(this.periodClass)) { 319 return false; 320 } 321 if (!info.dateFormat.equals(this.dateFormat)) { 322 return false; 323 } 324 if (!info.padding.equals(this.padding)) { 325 return false; 326 } 327 if (!info.labelFont.equals(this.labelFont)) { 328 return false; 329 } 330 if (!info.labelPaint.equals(this.labelPaint)) { 331 return false; 332 } 333 if (info.drawDividers != this.drawDividers) { 334 return false; 335 } 336 if (!info.dividerStroke.equals(this.dividerStroke)) { 337 return false; 338 } 339 if (!info.dividerPaint.equals(this.dividerPaint)) { 340 return false; 341 } 342 return true; 343 } 344 return false; 345 } 346 347 /** 348 * Returns a hash code for this object. 349 * 350 * @return A hash code. 351 */ 352 public int hashCode() { 353 int result = 41; 354 result = 37 * this.periodClass.hashCode(); 355 result = 37 * this.dateFormat.hashCode(); 356 return result; 357 } 358 359 /** 360 * Returns a clone of the object. 361 * 362 * @return A clone. 363 * 364 * @throws CloneNotSupportedException if cloning is not supported. 365 */ 366 public Object clone() throws CloneNotSupportedException { 367 PeriodAxisLabelInfo clone = (PeriodAxisLabelInfo) super.clone(); 368 return clone; 369 } 370 371 /** 372 * Provides serialization support. 373 * 374 * @param stream the output stream. 375 * 376 * @throws IOException if there is an I/O error. 377 */ 378 private void writeObject(ObjectOutputStream stream) throws IOException { 379 stream.defaultWriteObject(); 380 SerialUtilities.writePaint(this.labelPaint, stream); 381 SerialUtilities.writeStroke(this.dividerStroke, stream); 382 SerialUtilities.writePaint(this.dividerPaint, stream); 383 } 384 385 /** 386 * Provides serialization support. 387 * 388 * @param stream the input stream. 389 * 390 * @throws IOException if there is an I/O error. 391 * @throws ClassNotFoundException if there is a classpath problem. 392 */ 393 private void readObject(ObjectInputStream stream) 394 throws IOException, ClassNotFoundException { 395 stream.defaultReadObject(); 396 this.labelPaint = SerialUtilities.readPaint(stream); 397 this.dividerStroke = SerialUtilities.readStroke(stream); 398 this.dividerPaint = SerialUtilities.readPaint(stream); 399 } 400 401 }