1 48 49 package org.jfree.chart.axis; 50 51 import java.awt.Color ; 52 import java.awt.Font ; 53 import java.awt.FontMetrics ; 54 import java.awt.Graphics2D ; 55 import java.awt.Paint ; 56 import java.awt.geom.Rectangle2D ; 57 import java.io.IOException ; 58 import java.io.ObjectInputStream ; 59 import java.io.ObjectOutputStream ; 60 import java.io.Serializable ; 61 import java.util.Iterator ; 62 import java.util.List ; 63 64 import org.jfree.chart.event.AxisChangeEvent; 65 import org.jfree.chart.plot.CategoryPlot; 66 import org.jfree.chart.plot.Plot; 67 import org.jfree.chart.plot.PlotRenderingInfo; 68 import org.jfree.data.category.CategoryDataset; 69 import org.jfree.io.SerialUtilities; 70 import org.jfree.text.TextUtilities; 71 import org.jfree.ui.RectangleEdge; 72 import org.jfree.ui.TextAnchor; 73 74 77 public class SubCategoryAxis extends CategoryAxis 78 implements Cloneable , Serializable { 79 80 81 private static final long serialVersionUID = -1279463299793228344L; 82 83 84 private List subCategories; 85 86 87 private Font subLabelFont = new Font ("SansSerif", Font.PLAIN, 10); 88 89 90 private transient Paint subLabelPaint = Color.black; 91 92 97 public SubCategoryAxis(String label) { 98 super(label); 99 this.subCategories = new java.util.ArrayList (); 100 } 101 102 107 public void addSubCategory(Comparable subCategory) { 108 this.subCategories.add(subCategory); 109 } 110 111 116 public Font getSubLabelFont() { 117 return this.subLabelFont; 118 } 119 120 126 public void setSubLabelFont(Font font) { 127 if (font == null) { 128 throw new IllegalArgumentException ("Null 'font' argument."); 129 } 130 this.subLabelFont = font; 131 notifyListeners(new AxisChangeEvent(this)); 132 } 133 134 139 public Paint getSubLabelPaint() { 140 return this.subLabelPaint; 141 } 142 143 149 public void setSubLabelPaint(Paint paint) { 150 if (paint == null) { 151 throw new IllegalArgumentException ("Null 'paint' argument."); 152 } 153 this.subLabelPaint = paint; 154 notifyListeners(new AxisChangeEvent(this)); 155 } 156 157 168 public AxisSpace reserveSpace(Graphics2D g2, Plot plot, 169 Rectangle2D plotArea, 170 RectangleEdge edge, AxisSpace space) { 171 172 if (space == null) { 174 space = new AxisSpace(); 175 } 176 177 if (!isVisible()) { 179 return space; 180 } 181 182 space = super.reserveSpace(g2, plot, plotArea, edge, space); 183 double maxdim = getMaxDim(g2, edge); 184 if (RectangleEdge.isTopOrBottom(edge)) { 185 space.add(maxdim, edge); 186 } 187 else if (RectangleEdge.isLeftOrRight(edge)) { 188 space.add(maxdim, edge); 189 } 190 return space; 191 } 192 193 202 private double getMaxDim(Graphics2D g2, RectangleEdge edge) { 203 double result = 0.0; 204 g2.setFont(this.subLabelFont); 205 FontMetrics fm = g2.getFontMetrics(); 206 Iterator iterator = this.subCategories.iterator(); 207 while (iterator.hasNext()) { 208 Comparable subcategory = (Comparable ) iterator.next(); 209 String label = subcategory.toString(); 210 Rectangle2D bounds = TextUtilities.getTextBounds(label, g2, fm); 211 double dim = 0.0; 212 if (RectangleEdge.isLeftOrRight(edge)) { 213 dim = bounds.getWidth(); 214 } 215 else { dim = bounds.getHeight(); 217 } 218 result = Math.max(result, dim); 219 } 220 return result; 221 } 222 223 239 public AxisState draw(Graphics2D g2, 240 double cursor, 241 Rectangle2D plotArea, 242 Rectangle2D dataArea, 243 RectangleEdge edge, 244 PlotRenderingInfo plotState) { 245 246 if (!isVisible()) { 248 return new AxisState(cursor); 249 } 250 251 if (isAxisLineVisible()) { 252 drawAxisLine(g2, cursor, dataArea, edge); 253 } 254 255 AxisState state = new AxisState(cursor); 257 state = drawSubCategoryLabels( 258 g2, plotArea, dataArea, edge, state, plotState 259 ); 260 state = drawCategoryLabels(g2, plotArea, dataArea, edge, state, 261 plotState); 262 state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state); 263 264 return state; 265 266 } 267 268 282 protected AxisState drawSubCategoryLabels(Graphics2D g2, 283 Rectangle2D plotArea, 284 Rectangle2D dataArea, 285 RectangleEdge edge, 286 AxisState state, 287 PlotRenderingInfo plotState) { 288 289 if (state == null) { 290 throw new IllegalArgumentException ("Null 'state' argument."); 291 } 292 293 g2.setFont(this.subLabelFont); 294 g2.setPaint(this.subLabelPaint); 295 CategoryPlot plot = (CategoryPlot) getPlot(); 296 CategoryDataset dataset = plot.getDataset(); 297 int categoryCount = dataset.getColumnCount(); 298 299 double maxdim = getMaxDim(g2, edge); 300 for (int categoryIndex = 0; categoryIndex < categoryCount; 301 categoryIndex++) { 302 303 double x0 = 0.0; 304 double x1 = 0.0; 305 double y0 = 0.0; 306 double y1 = 0.0; 307 if (edge == RectangleEdge.TOP) { 308 x0 = getCategoryStart(categoryIndex, categoryCount, dataArea, 309 edge); 310 x1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, 311 edge); 312 y1 = state.getCursor(); 313 y0 = y1 - maxdim; 314 } 315 else if (edge == RectangleEdge.BOTTOM) { 316 x0 = getCategoryStart(categoryIndex, categoryCount, dataArea, 317 edge); 318 x1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, 319 edge); 320 y0 = state.getCursor(); 321 y1 = y0 + maxdim; 322 } 323 else if (edge == RectangleEdge.LEFT) { 324 y0 = getCategoryStart(categoryIndex, categoryCount, dataArea, 325 edge); 326 y1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, 327 edge); 328 x1 = state.getCursor(); 329 x0 = x1 - maxdim; 330 } 331 else if (edge == RectangleEdge.RIGHT) { 332 y0 = getCategoryStart(categoryIndex, categoryCount, dataArea, 333 edge); 334 y1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, 335 edge); 336 x0 = state.getCursor(); 337 x1 = x0 + maxdim; 338 } 339 Rectangle2D area = new Rectangle2D.Double (x0, y0, (x1 - x0), 340 (y1 - y0)); 341 int subCategoryCount = this.subCategories.size(); 342 float width = (float) ((x1 - x0) / subCategoryCount); 343 float height = (float) ((y1 - y0) / subCategoryCount); 344 float xx = 0.0f; 345 float yy = 0.0f; 346 for (int i = 0; i < subCategoryCount; i++) { 347 if (RectangleEdge.isTopOrBottom(edge)) { 348 xx = (float) (x0 + (i + 0.5) * width); 349 yy = (float) area.getCenterY(); 350 } 351 else { 352 xx = (float) area.getCenterX(); 353 yy = (float) (y0 + (i + 0.5) * height); 354 } 355 String label = this.subCategories.get(i).toString(); 356 TextUtilities.drawRotatedString(label, g2, xx, yy, 357 TextAnchor.CENTER, 0.0, TextAnchor.CENTER); 358 } 359 } 360 361 if (edge.equals(RectangleEdge.TOP)) { 362 double h = maxdim; 363 state.cursorUp(h); 364 } 365 else if (edge.equals(RectangleEdge.BOTTOM)) { 366 double h = maxdim; 367 state.cursorDown(h); 368 } 369 else if (edge == RectangleEdge.LEFT) { 370 double w = maxdim; 371 state.cursorLeft(w); 372 } 373 else if (edge == RectangleEdge.RIGHT) { 374 double w = maxdim; 375 state.cursorRight(w); 376 } 377 return state; 378 } 379 380 387 public boolean equals(Object obj) { 388 if (obj == this) { 389 return true; 390 } 391 if (obj instanceof SubCategoryAxis && super.equals(obj)) { 392 SubCategoryAxis axis = (SubCategoryAxis) obj; 393 if (!this.subCategories.equals(axis.subCategories)) { 394 return false; 395 } 396 if (!this.subLabelFont.equals(axis.subLabelFont)) { 397 return false; 398 } 399 if (!this.subLabelPaint.equals(axis.subLabelPaint)) { 400 return false; 401 } 402 return true; 403 } 404 return false; 405 } 406 407 414 private void writeObject(ObjectOutputStream stream) throws IOException { 415 stream.defaultWriteObject(); 416 SerialUtilities.writePaint(this.subLabelPaint, stream); 417 } 418 419 427 private void readObject(ObjectInputStream stream) 428 throws IOException , ClassNotFoundException { 429 stream.defaultReadObject(); 430 this.subLabelPaint = SerialUtilities.readPaint(stream); 431 } 432 433 } 434 | Popular Tags |