001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2013, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * ------------------------ 028 * PeriodAxisLabelInfo.java 029 * ------------------------ 030 * (C) Copyright 2004-2013, 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 * 02-Jul-2013 : Use ParamChecks (DG); 044 * 045 */ 046 047package org.jfree.chart.axis; 048 049import java.awt.BasicStroke; 050import java.awt.Color; 051import java.awt.Font; 052import java.awt.Paint; 053import java.awt.Stroke; 054import java.io.IOException; 055import java.io.ObjectInputStream; 056import java.io.ObjectOutputStream; 057import java.io.Serializable; 058import java.lang.reflect.Constructor; 059import java.text.DateFormat; 060import java.util.Date; 061import java.util.Locale; 062import java.util.TimeZone; 063import org.jfree.chart.util.ParamChecks; 064 065import org.jfree.data.time.RegularTimePeriod; 066import org.jfree.io.SerialUtilities; 067import org.jfree.ui.RectangleInsets; 068 069/** 070 * A record that contains information for one "band" of date labels in 071 * a {@link PeriodAxis}. 072 */ 073public class PeriodAxisLabelInfo implements Cloneable, Serializable { 074 075 /** For serialization. */ 076 private static final long serialVersionUID = 5710451740920277357L; 077 078 /** The default insets. */ 079 public static final RectangleInsets DEFAULT_INSETS 080 = new RectangleInsets(2, 2, 2, 2); 081 082 /** The default font. */ 083 public static final Font DEFAULT_FONT 084 = new Font("SansSerif", Font.PLAIN, 10); 085 086 /** The default label paint. */ 087 public static final Paint DEFAULT_LABEL_PAINT = Color.black; 088 089 /** The default divider stroke. */ 090 public static final Stroke DEFAULT_DIVIDER_STROKE = new BasicStroke(0.5f); 091 092 /** The default divider paint. */ 093 public static final Paint DEFAULT_DIVIDER_PAINT = Color.gray; 094 095 /** The subclass of {@link RegularTimePeriod} to use for this band. */ 096 private Class periodClass; 097 098 /** Controls the gaps around the band. */ 099 private RectangleInsets padding; 100 101 /** The date formatter. */ 102 private DateFormat dateFormat; 103 104 /** The label font. */ 105 private Font labelFont; 106 107 /** The label paint. */ 108 private transient Paint labelPaint; 109 110 /** A flag that controls whether or not dividers are visible. */ 111 private boolean drawDividers; 112 113 /** The stroke used to draw the dividers. */ 114 private transient Stroke dividerStroke; 115 116 /** The paint used to draw the dividers. */ 117 private transient Paint dividerPaint; 118 119 /** 120 * Creates a new instance. 121 * 122 * @param periodClass the subclass of {@link RegularTimePeriod} to use 123 * (<code>null</code> not permitted). 124 * @param dateFormat the date format (<code>null</code> not permitted). 125 */ 126 public PeriodAxisLabelInfo(Class periodClass, DateFormat dateFormat) { 127 this(periodClass, dateFormat, DEFAULT_INSETS, DEFAULT_FONT, 128 DEFAULT_LABEL_PAINT, true, DEFAULT_DIVIDER_STROKE, 129 DEFAULT_DIVIDER_PAINT); 130 } 131 132 /** 133 * Creates a new instance. 134 * 135 * @param periodClass the subclass of {@link RegularTimePeriod} to use 136 * (<code>null</code> not permitted). 137 * @param dateFormat the date format (<code>null</code> not permitted). 138 * @param padding controls the space around the band (<code>null</code> 139 * not permitted). 140 * @param labelFont the label font (<code>null</code> not permitted). 141 * @param labelPaint the label paint (<code>null</code> not permitted). 142 * @param drawDividers a flag that controls whether dividers are drawn. 143 * @param dividerStroke the stroke used to draw the dividers 144 * (<code>null</code> not permitted). 145 * @param dividerPaint the paint used to draw the dividers 146 * (<code>null</code> not permitted). 147 */ 148 public PeriodAxisLabelInfo(Class periodClass, DateFormat dateFormat, 149 RectangleInsets padding, Font labelFont, Paint labelPaint, 150 boolean drawDividers, Stroke dividerStroke, Paint dividerPaint) { 151 ParamChecks.nullNotPermitted(periodClass, "periodClass"); 152 ParamChecks.nullNotPermitted(dateFormat, "dateFormat"); 153 ParamChecks.nullNotPermitted(padding, "padding"); 154 ParamChecks.nullNotPermitted(labelFont, "labelFont"); 155 ParamChecks.nullNotPermitted(labelPaint, "labelPaint"); 156 ParamChecks.nullNotPermitted(dividerStroke, "dividerStroke"); 157 ParamChecks.nullNotPermitted(dividerPaint, "dividerPaint"); 158 this.periodClass = periodClass; 159 this.dateFormat = (DateFormat) dateFormat.clone(); 160 this.padding = padding; 161 this.labelFont = labelFont; 162 this.labelPaint = labelPaint; 163 this.drawDividers = drawDividers; 164 this.dividerStroke = dividerStroke; 165 this.dividerPaint = dividerPaint; 166 } 167 168 /** 169 * Returns the subclass of {@link RegularTimePeriod} that should be used 170 * to generate the date labels. 171 * 172 * @return The class. 173 */ 174 public Class getPeriodClass() { 175 return this.periodClass; 176 } 177 178 /** 179 * Returns a copy of the date formatter. 180 * 181 * @return A copy of the date formatter (never <code>null</code>). 182 */ 183 public DateFormat getDateFormat() { 184 return (DateFormat) this.dateFormat.clone(); 185 } 186 187 /** 188 * Returns the padding for the band. 189 * 190 * @return The padding. 191 */ 192 public RectangleInsets getPadding() { 193 return this.padding; 194 } 195 196 /** 197 * Returns the label font. 198 * 199 * @return The label font (never <code>null</code>). 200 */ 201 public Font getLabelFont() { 202 return this.labelFont; 203 } 204 205 /** 206 * Returns the label paint. 207 * 208 * @return The label paint. 209 */ 210 public Paint getLabelPaint() { 211 return this.labelPaint; 212 } 213 214 /** 215 * Returns a flag that controls whether or not dividers are drawn. 216 * 217 * @return A flag. 218 */ 219 public boolean getDrawDividers() { 220 return this.drawDividers; 221 } 222 223 /** 224 * Returns the stroke used to draw the dividers. 225 * 226 * @return The stroke. 227 */ 228 public Stroke getDividerStroke() { 229 return this.dividerStroke; 230 } 231 232 /** 233 * Returns the paint used to draw the dividers. 234 * 235 * @return The paint. 236 */ 237 public Paint getDividerPaint() { 238 return this.dividerPaint; 239 } 240 241 /** 242 * Creates a time period that includes the specified millisecond, assuming 243 * the given time zone. 244 * 245 * @param millisecond the time. 246 * @param zone the time zone. 247 * 248 * @return The time period. 249 * 250 * @deprecated As of 1.0.13, use the method that specifies the locale also. 251 */ 252 public RegularTimePeriod createInstance(Date millisecond, TimeZone zone) { 253 return createInstance(millisecond, zone, Locale.getDefault()); 254 } 255 256 /** 257 * Creates a time period that includes the specified millisecond, assuming 258 * the given time zone. 259 * 260 * @param millisecond the time. 261 * @param zone the time zone. 262 * @param locale the locale. 263 * 264 * @return The time period. 265 * 266 * @since 1.0.13. 267 */ 268 public RegularTimePeriod createInstance(Date millisecond, TimeZone zone, 269 Locale locale) { 270 RegularTimePeriod result = null; 271 try { 272 Constructor c = this.periodClass.getDeclaredConstructor( 273 new Class[] {Date.class, TimeZone.class, Locale.class}); 274 result = (RegularTimePeriod) c.newInstance(new Object[] { 275 millisecond, zone, locale}); 276 } 277 catch (Exception e) { 278 // do nothing 279 } 280 return result; 281 } 282 283 /** 284 * Tests this object for equality with an arbitrary object. 285 * 286 * @param obj the object to test against (<code>null</code> permitted). 287 * 288 * @return A boolean. 289 */ 290 @Override 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 @Override 332 public int hashCode() { 333 int result = 41; 334 result = result + 37 * this.periodClass.hashCode(); 335 result = result + 37 * this.dateFormat.hashCode(); 336 return result; 337 } 338 339 /** 340 * Returns a clone of the object. 341 * 342 * @return A clone. 343 * 344 * @throws CloneNotSupportedException if cloning is not supported. 345 */ 346 @Override 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}