1 93 94 package org.jfree.chart.renderer.category; 95 96 import java.awt.GradientPaint ; 97 import java.awt.Graphics2D ; 98 import java.awt.Paint ; 99 import java.awt.geom.Rectangle2D ; 100 import java.io.Serializable ; 101 102 import org.jfree.chart.axis.CategoryAxis; 103 import org.jfree.chart.axis.ValueAxis; 104 import org.jfree.chart.entity.EntityCollection; 105 import org.jfree.chart.event.RendererChangeEvent; 106 import org.jfree.chart.labels.CategoryItemLabelGenerator; 107 import org.jfree.chart.labels.ItemLabelAnchor; 108 import org.jfree.chart.labels.ItemLabelPosition; 109 import org.jfree.chart.plot.CategoryPlot; 110 import org.jfree.chart.plot.PlotOrientation; 111 import org.jfree.data.DataUtilities; 112 import org.jfree.data.Range; 113 import org.jfree.data.category.CategoryDataset; 114 import org.jfree.data.general.DatasetUtilities; 115 import org.jfree.ui.GradientPaintTransformer; 116 import org.jfree.ui.RectangleEdge; 117 import org.jfree.ui.TextAnchor; 118 import org.jfree.util.PublicCloneable; 119 120 124 public class StackedBarRenderer extends BarRenderer 125 implements Cloneable , PublicCloneable, 126 Serializable { 127 128 129 static final long serialVersionUID = 6402943811500067531L; 130 131 132 private boolean renderAsPercentages; 133 134 141 public StackedBarRenderer() { 142 this(false); 143 } 144 145 151 public StackedBarRenderer(boolean renderAsPercentages) { 152 super(); 153 this.renderAsPercentages = renderAsPercentages; 154 155 ItemLabelPosition p = new ItemLabelPosition(ItemLabelAnchor.CENTER, 158 TextAnchor.CENTER); 159 setBasePositiveItemLabelPosition(p); 160 setBaseNegativeItemLabelPosition(p); 161 setPositiveItemLabelPositionFallback(null); 162 setNegativeItemLabelPositionFallback(null); 163 } 164 165 172 public boolean getRenderAsPercentages() { 173 return this.renderAsPercentages; 174 } 175 176 183 public void setRenderAsPercentages(boolean asPercentages) { 184 this.renderAsPercentages = asPercentages; 185 notifyListeners(new RendererChangeEvent(this)); 186 } 187 188 195 public int getPassCount() { 196 return 2; 197 } 198 199 207 public Range findRangeBounds(CategoryDataset dataset) { 208 if (this.renderAsPercentages) { 209 return new Range(0.0, 1.0); 210 } 211 else { 212 return DatasetUtilities.findStackedRangeBounds(dataset, getBase()); 213 } 214 } 215 216 224 protected void calculateBarWidth(CategoryPlot plot, 225 Rectangle2D dataArea, 226 int rendererIndex, 227 CategoryItemRendererState state) { 228 229 CategoryAxis xAxis = plot.getDomainAxisForDataset(rendererIndex); 231 CategoryDataset data = plot.getDataset(rendererIndex); 232 if (data != null) { 233 PlotOrientation orientation = plot.getOrientation(); 234 double space = 0.0; 235 if (orientation == PlotOrientation.HORIZONTAL) { 236 space = dataArea.getHeight(); 237 } 238 else if (orientation == PlotOrientation.VERTICAL) { 239 space = dataArea.getWidth(); 240 } 241 double maxWidth = space * getMaximumBarWidth(); 242 int columns = data.getColumnCount(); 243 double categoryMargin = 0.0; 244 if (columns > 1) { 245 categoryMargin = xAxis.getCategoryMargin(); 246 } 247 248 double used = space * (1 - xAxis.getLowerMargin() 249 - xAxis.getUpperMargin() 250 - categoryMargin); 251 if (columns > 0) { 252 state.setBarWidth(Math.min(used / columns, maxWidth)); 253 } 254 else { 255 state.setBarWidth(Math.min(used, maxWidth)); 256 } 257 } 258 259 } 260 261 275 public void drawItem(Graphics2D g2, 276 CategoryItemRendererState state, 277 Rectangle2D dataArea, 278 CategoryPlot plot, 279 CategoryAxis domainAxis, 280 ValueAxis rangeAxis, 281 CategoryDataset dataset, 282 int row, 283 int column, 284 int pass) { 285 286 Number dataValue = dataset.getValue(row, column); 288 if (dataValue == null) { 289 return; 290 } 291 292 double value = dataValue.doubleValue(); 293 double total = 0.0; if (this.renderAsPercentages) { 295 total = DataUtilities.calculateColumnTotal(dataset, column); 296 value = value / total; 297 } 298 299 PlotOrientation orientation = plot.getOrientation(); 300 double barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(), 301 dataArea, plot.getDomainAxisEdge()) 302 - state.getBarWidth() / 2.0; 303 304 double positiveBase = getBase(); 305 double negativeBase = positiveBase; 306 307 for (int i = 0; i < row; i++) { 308 Number v = dataset.getValue(i, column); 309 if (v != null) { 310 double d = v.doubleValue(); 311 if (this.renderAsPercentages) { 312 d = d / total; 313 } 314 if (d > 0) { 315 positiveBase = positiveBase + d; 316 } 317 else { 318 negativeBase = negativeBase + d; 319 } 320 } 321 } 322 323 double translatedBase; 324 double translatedValue; 325 RectangleEdge location = plot.getRangeAxisEdge(); 326 if (value >= 0.0) { 327 translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea, 328 location); 329 translatedValue = rangeAxis.valueToJava2D(positiveBase + value, 330 dataArea, location); 331 } 332 else { 333 translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea, 334 location); 335 translatedValue = rangeAxis.valueToJava2D(negativeBase + value, 336 dataArea, location); 337 } 338 double barL0 = Math.min(translatedBase, translatedValue); 339 double barLength = Math.max(Math.abs(translatedValue - translatedBase), 340 getMinimumBarLength()); 341 342 Rectangle2D bar = null; 343 if (orientation == PlotOrientation.HORIZONTAL) { 344 bar = new Rectangle2D.Double (barL0, barW0, barLength, 345 state.getBarWidth()); 346 } 347 else { 348 bar = new Rectangle2D.Double (barW0, barL0, state.getBarWidth(), 349 barLength); 350 } 351 if (pass == 0) { 352 Paint itemPaint = getItemPaint(row, column); 353 GradientPaintTransformer t = getGradientPaintTransformer(); 354 if (t != null && itemPaint instanceof GradientPaint ) { 355 itemPaint = t.transform((GradientPaint ) itemPaint, bar); 356 } 357 g2.setPaint(itemPaint); 358 g2.fill(bar); 359 if (isDrawBarOutline() 360 && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 361 g2.setStroke(getItemOutlineStroke(row, column)); 362 g2.setPaint(getItemOutlinePaint(row, column)); 363 g2.draw(bar); 364 } 365 366 EntityCollection entities = state.getEntityCollection(); 368 if (entities != null) { 369 addItemEntity(entities, dataset, row, column, bar); 370 } 371 } 372 else if (pass == 1) { 373 CategoryItemLabelGenerator generator 374 = getItemLabelGenerator(row, column); 375 if (generator != null && isItemLabelVisible(row, column)) { 376 drawItemLabel(g2, dataset, row, column, plot, generator, bar, 377 (value < 0.0)); 378 } 379 } 380 } 381 382 389 public boolean equals(Object obj) { 390 if (obj == this) { 391 return true; 392 } 393 if (!(obj instanceof StackedBarRenderer)) { 394 return false; 395 } 396 if (!super.equals(obj)) { 397 return false; 398 } 399 StackedBarRenderer that = (StackedBarRenderer) obj; 400 if (this.renderAsPercentages != that.renderAsPercentages) { 401 return false; 402 } 403 return true; 404 } 405 406 } 407 | Popular Tags |