001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert 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-present, by David Gilbert and Contributors. 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): -; 034 * 035 */ 036 037package org.jfree.chart.axis; 038 039import java.awt.BasicStroke; 040import java.awt.Color; 041import java.awt.Font; 042import java.awt.Paint; 043import java.awt.Stroke; 044import java.io.IOException; 045import java.io.ObjectInputStream; 046import java.io.ObjectOutputStream; 047import java.io.Serializable; 048import java.lang.reflect.Constructor; 049import java.text.DateFormat; 050import java.util.Date; 051import java.util.Locale; 052import java.util.TimeZone; 053import org.jfree.chart.ui.RectangleInsets; 054import org.jfree.chart.util.Args; 055import org.jfree.chart.util.SerialUtils; 056 057import org.jfree.data.time.RegularTimePeriod; 058 059/** 060 * A record that contains information for one "band" of date labels in 061 * a {@link PeriodAxis}. 062 */ 063public class PeriodAxisLabelInfo implements Cloneable, Serializable { 064 065 /** For serialization. */ 066 private static final long serialVersionUID = 5710451740920277357L; 067 068 /** The default insets. */ 069 public static final RectangleInsets DEFAULT_INSETS 070 = new RectangleInsets(2, 2, 2, 2); 071 072 /** The default font. */ 073 public static final Font DEFAULT_FONT 074 = new Font("SansSerif", Font.PLAIN, 10); 075 076 /** The default label paint. */ 077 public static final Paint DEFAULT_LABEL_PAINT = Color.BLACK; 078 079 /** The default divider stroke. */ 080 public static final Stroke DEFAULT_DIVIDER_STROKE = new BasicStroke(0.5f); 081 082 /** The default divider paint. */ 083 public static final Paint DEFAULT_DIVIDER_PAINT = Color.GRAY; 084 085 /** The subclass of {@link RegularTimePeriod} to use for this band. */ 086 private Class periodClass; 087 088 /** Controls the gaps around the band. */ 089 private RectangleInsets padding; 090 091 /** The date formatter. */ 092 private DateFormat dateFormat; 093 094 /** The label font. */ 095 private Font labelFont; 096 097 /** The label paint. */ 098 private transient Paint labelPaint; 099 100 /** A flag that controls whether or not dividers are visible. */ 101 private boolean drawDividers; 102 103 /** The stroke used to draw the dividers. */ 104 private transient Stroke dividerStroke; 105 106 /** The paint used to draw the dividers. */ 107 private transient Paint dividerPaint; 108 109 /** 110 * Creates a new instance. 111 * 112 * @param periodClass the subclass of {@link RegularTimePeriod} to use 113 * ({@code null} not permitted). 114 * @param dateFormat the date format ({@code null} not permitted). 115 */ 116 public PeriodAxisLabelInfo(Class periodClass, DateFormat dateFormat) { 117 this(periodClass, dateFormat, DEFAULT_INSETS, DEFAULT_FONT, 118 DEFAULT_LABEL_PAINT, true, DEFAULT_DIVIDER_STROKE, 119 DEFAULT_DIVIDER_PAINT); 120 } 121 122 /** 123 * Creates a new instance. 124 * 125 * @param periodClass the subclass of {@link RegularTimePeriod} to use 126 * ({@code null} not permitted). 127 * @param dateFormat the date format ({@code null} not permitted). 128 * @param padding controls the space around the band ({@code null} 129 * not permitted). 130 * @param labelFont the label font ({@code null} not permitted). 131 * @param labelPaint the label paint ({@code null} not permitted). 132 * @param drawDividers a flag that controls whether dividers are drawn. 133 * @param dividerStroke the stroke used to draw the dividers 134 * ({@code null} not permitted). 135 * @param dividerPaint the paint used to draw the dividers 136 * ({@code null} not permitted). 137 */ 138 public PeriodAxisLabelInfo(Class periodClass, DateFormat dateFormat, 139 RectangleInsets padding, Font labelFont, Paint labelPaint, 140 boolean drawDividers, Stroke dividerStroke, Paint dividerPaint) { 141 Args.nullNotPermitted(periodClass, "periodClass"); 142 Args.nullNotPermitted(dateFormat, "dateFormat"); 143 Args.nullNotPermitted(padding, "padding"); 144 Args.nullNotPermitted(labelFont, "labelFont"); 145 Args.nullNotPermitted(labelPaint, "labelPaint"); 146 Args.nullNotPermitted(dividerStroke, "dividerStroke"); 147 Args.nullNotPermitted(dividerPaint, "dividerPaint"); 148 this.periodClass = periodClass; 149 this.dateFormat = (DateFormat) dateFormat.clone(); 150 this.padding = padding; 151 this.labelFont = labelFont; 152 this.labelPaint = labelPaint; 153 this.drawDividers = drawDividers; 154 this.dividerStroke = dividerStroke; 155 this.dividerPaint = dividerPaint; 156 } 157 158 /** 159 * Returns the subclass of {@link RegularTimePeriod} that should be used 160 * to generate the date labels. 161 * 162 * @return The class. 163 */ 164 public Class getPeriodClass() { 165 return this.periodClass; 166 } 167 168 /** 169 * Returns a copy of the date formatter. 170 * 171 * @return A copy of the date formatter (never {@code null}). 172 */ 173 public DateFormat getDateFormat() { 174 return (DateFormat) this.dateFormat.clone(); 175 } 176 177 /** 178 * Returns the padding for the band. 179 * 180 * @return The padding. 181 */ 182 public RectangleInsets getPadding() { 183 return this.padding; 184 } 185 186 /** 187 * Returns the label font. 188 * 189 * @return The label font (never {@code null}). 190 */ 191 public Font getLabelFont() { 192 return this.labelFont; 193 } 194 195 /** 196 * Returns the label paint. 197 * 198 * @return The label paint. 199 */ 200 public Paint getLabelPaint() { 201 return this.labelPaint; 202 } 203 204 /** 205 * Returns a flag that controls whether or not dividers are drawn. 206 * 207 * @return A flag. 208 */ 209 public boolean getDrawDividers() { 210 return this.drawDividers; 211 } 212 213 /** 214 * Returns the stroke used to draw the dividers. 215 * 216 * @return The stroke. 217 */ 218 public Stroke getDividerStroke() { 219 return this.dividerStroke; 220 } 221 222 /** 223 * Returns the paint used to draw the dividers. 224 * 225 * @return The paint. 226 */ 227 public Paint getDividerPaint() { 228 return this.dividerPaint; 229 } 230 231 /** 232 * Creates a time period that includes the specified millisecond, assuming 233 * the given time zone. 234 * 235 * @param millisecond the time. 236 * @param zone the time zone. 237 * @param locale the locale. 238 * 239 * @return The time period. 240 */ 241 public RegularTimePeriod createInstance(Date millisecond, TimeZone zone, 242 Locale locale) { 243 RegularTimePeriod result = null; 244 try { 245 Constructor c = this.periodClass.getDeclaredConstructor( 246 new Class[] {Date.class, TimeZone.class, Locale.class}); 247 result = (RegularTimePeriod) c.newInstance(new Object[] { 248 millisecond, zone, locale}); 249 } 250 catch (Exception e) { 251 // do nothing 252 } 253 return result; 254 } 255 256 /** 257 * Tests this object for equality with an arbitrary object. 258 * 259 * @param obj the object to test against ({@code null} permitted). 260 * 261 * @return A boolean. 262 */ 263 @Override 264 public boolean equals(Object obj) { 265 if (obj == this) { 266 return true; 267 } 268 if (obj instanceof PeriodAxisLabelInfo) { 269 PeriodAxisLabelInfo info = (PeriodAxisLabelInfo) obj; 270 if (!info.periodClass.equals(this.periodClass)) { 271 return false; 272 } 273 if (!info.dateFormat.equals(this.dateFormat)) { 274 return false; 275 } 276 if (!info.padding.equals(this.padding)) { 277 return false; 278 } 279 if (!info.labelFont.equals(this.labelFont)) { 280 return false; 281 } 282 if (!info.labelPaint.equals(this.labelPaint)) { 283 return false; 284 } 285 if (info.drawDividers != this.drawDividers) { 286 return false; 287 } 288 if (!info.dividerStroke.equals(this.dividerStroke)) { 289 return false; 290 } 291 if (!info.dividerPaint.equals(this.dividerPaint)) { 292 return false; 293 } 294 return true; 295 } 296 return false; 297 } 298 299 /** 300 * Returns a hash code for this object. 301 * 302 * @return A hash code. 303 */ 304 @Override 305 public int hashCode() { 306 int result = 41; 307 result = result + 37 * this.periodClass.hashCode(); 308 result = result + 37 * this.dateFormat.hashCode(); 309 return result; 310 } 311 312 /** 313 * Returns a clone of the object. 314 * 315 * @return A clone. 316 * 317 * @throws CloneNotSupportedException if cloning is not supported. 318 */ 319 @Override 320 public Object clone() throws CloneNotSupportedException { 321 PeriodAxisLabelInfo clone = (PeriodAxisLabelInfo) super.clone(); 322 return clone; 323 } 324 325 /** 326 * Provides serialization support. 327 * 328 * @param stream the output stream. 329 * 330 * @throws IOException if there is an I/O error. 331 */ 332 private void writeObject(ObjectOutputStream stream) throws IOException { 333 stream.defaultWriteObject(); 334 SerialUtils.writePaint(this.labelPaint, stream); 335 SerialUtils.writeStroke(this.dividerStroke, stream); 336 SerialUtils.writePaint(this.dividerPaint, stream); 337 } 338 339 /** 340 * Provides serialization support. 341 * 342 * @param stream the input stream. 343 * 344 * @throws IOException if there is an I/O error. 345 * @throws ClassNotFoundException if there is a classpath problem. 346 */ 347 private void readObject(ObjectInputStream stream) 348 throws IOException, ClassNotFoundException { 349 stream.defaultReadObject(); 350 this.labelPaint = SerialUtils.readPaint(stream); 351 this.dividerStroke = SerialUtils.readStroke(stream); 352 this.dividerPaint = SerialUtils.readPaint(stream); 353 } 354 355}