1 37 38 package org.jfree.chart.demo; 39 40 import java.awt.Color ; 41 import java.awt.Font ; 42 import java.awt.Graphics2D ; 43 import java.awt.Paint ; 44 import java.awt.geom.Rectangle2D ; 45 46 import org.jfree.chart.axis.CategoryAxis; 47 import org.jfree.chart.axis.ValueAxis; 48 import org.jfree.chart.entity.CategoryItemEntity; 49 import org.jfree.chart.entity.EntityCollection; 50 import org.jfree.chart.labels.CategoryItemLabelGenerator; 51 import org.jfree.chart.plot.CategoryPlot; 52 import org.jfree.chart.plot.PlotOrientation; 53 import org.jfree.chart.renderer.CategoryItemRendererState; 54 import org.jfree.chart.renderer.StackedBarRenderer; 55 import org.jfree.data.CategoryDataset; 56 import org.jfree.ui.RectangleEdge; 57 import org.jfree.ui.RefineryUtilities; 58 import org.jfree.ui.TextAnchor; 59 60 64 public class ExtendedStackedBarRenderer extends StackedBarRenderer { 65 66 67 private boolean showPositiveTotal = true; 68 69 70 private boolean showNegativeTotal = true; 71 72 73 private Font totalLabelFont = new Font ("SansSerif", Font.PLAIN, 10); 74 75 78 public ExtendedStackedBarRenderer() { 79 super(); 80 } 81 82 93 106 public void drawItem(Graphics2D g2, 107 CategoryItemRendererState state, 108 Rectangle2D dataArea, 109 CategoryPlot plot, 110 CategoryAxis domainAxis, 111 ValueAxis rangeAxis, 112 CategoryDataset dataset, 113 int row, 114 int column) { 115 116 Number dataValue = dataset.getValue(row, column); 118 if (dataValue == null) { 119 return; 120 } 121 122 double value = dataValue.doubleValue(); 123 124 PlotOrientation orientation = plot.getOrientation(); 125 double barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(), dataArea, 126 plot.getDomainAxisEdge()) 127 - state.getBarWidth() / 2.0; 128 129 double positiveBase = 0.0; 130 double negativeBase = 0.0; 131 132 for (int i = 0; i < row; i++) { 133 Number v = dataset.getValue(i, column); 134 if (v != null) { 135 double d = v.doubleValue(); 136 if (d > 0) { 137 positiveBase = positiveBase + d; 138 } 139 else { 140 negativeBase = negativeBase + d; 141 } 142 } 143 } 144 145 double translatedBase; 146 double translatedValue; 147 RectangleEdge location = plot.getRangeAxisEdge(); 148 if (value > 0.0) { 149 translatedBase = rangeAxis.translateValueToJava2D(positiveBase, dataArea, location); 150 translatedValue = rangeAxis.translateValueToJava2D(positiveBase + value, dataArea, 151 location); 152 } 153 else { 154 translatedBase = rangeAxis.translateValueToJava2D(negativeBase, dataArea, location); 155 translatedValue = rangeAxis.translateValueToJava2D(negativeBase + value, dataArea, 156 location); 157 } 158 double barL0 = Math.min(translatedBase, translatedValue); 159 double barLength = Math.max(Math.abs(translatedValue - translatedBase), 160 getMinimumBarLength()); 161 162 Rectangle2D bar = null; 163 if (orientation == PlotOrientation.HORIZONTAL) { 164 bar = new Rectangle2D.Double (barL0, barW0, barLength, state.getBarWidth()); 165 } 166 else { 167 bar = new Rectangle2D.Double (barW0, barL0, state.getBarWidth(), barLength); 168 } 169 Paint seriesPaint = getItemPaint(row, column); 170 g2.setPaint(seriesPaint); 171 g2.fill(bar); 172 if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 173 g2.setStroke(getItemStroke(row, column)); 174 g2.setPaint(getItemOutlinePaint(row, column)); 175 g2.draw(bar); 176 } 177 178 CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column); 179 if (generator != null && isItemLabelVisible(row, column)) { 180 drawItemLabel(g2, dataset, row, column, plot, generator, bar, (value < 0.0)); 181 } 182 183 if (value > 0.0) { 184 if (this.showPositiveTotal) { 185 if (isLastPositiveItem(dataset, row, column)) { 186 g2.setPaint(Color.black); 187 g2.setFont(this.totalLabelFont); 188 double total = calculateSumOfPositiveValuesForCategory(dataset, column); 189 RefineryUtilities.drawRotatedString(String.valueOf(total), g2, 190 (float) bar.getCenterX(), 191 (float) (bar.getMinY() - 4.0), 192 TextAnchor.BOTTOM_CENTER, 193 TextAnchor.BOTTOM_CENTER, 194 0.0); 195 } 196 } 197 } 198 else { 199 if (this.showNegativeTotal) { 200 if (isLastNegativeItem(dataset, row, column)) { 201 g2.setPaint(Color.black); 202 g2.setFont(this.totalLabelFont); 203 double total = calculateSumOfNegativeValuesForCategory(dataset, column); 204 RefineryUtilities.drawRotatedString(String.valueOf(total), g2, 205 (float) bar.getCenterX(), 206 (float) (bar.getMaxY() + 4.0), 207 TextAnchor.TOP_CENTER, 208 TextAnchor.TOP_CENTER, 209 0.0); 210 } 211 } 212 } 213 214 if (state.getInfo() != null) { 216 EntityCollection entities = state.getInfo().getOwner().getEntityCollection(); 217 if (entities != null) { 218 String tip = null; 219 if (generator != null) { 220 tip = generator.generateToolTip(dataset, row, column); 221 } 222 String url = null; 223 if (getItemURLGenerator(row, column) != null) { 224 url = getItemURLGenerator(row, column).generateURL(dataset, row, column); 225 } 226 CategoryItemEntity entity = new CategoryItemEntity( 227 bar, tip, url, dataset, row, dataset.getColumnKey(column), column 228 ); 229 entities.addEntity(entity); 230 } 231 } 232 233 } 234 235 244 private boolean isLastPositiveItem(CategoryDataset dataset, int row, int column) { 245 boolean result = true; 246 Number dataValue = dataset.getValue(row, column); 247 if (dataValue == null) { 248 return false; } 250 for (int r = row + 1; r < dataset.getRowCount(); r++) { 251 dataValue = dataset.getValue(r, column); 252 if (dataValue != null) { 253 result = result && (dataValue.doubleValue() <= 0.0); 254 } 255 } 256 return result; 257 } 258 259 268 private boolean isLastNegativeItem(CategoryDataset dataset, int row, int column) { 269 boolean result = true; 270 Number dataValue = dataset.getValue(row, column); 271 if (dataValue == null) { 272 return false; } 274 for (int r = row + 1; r < dataset.getRowCount(); r++) { 275 dataValue = dataset.getValue(r, column); 276 if (dataValue != null) { 277 result = result && (dataValue.doubleValue() >= 0.0); 278 } 279 } 280 return result; 281 } 282 283 291 private double calculateSumOfPositiveValuesForCategory(CategoryDataset dataset, int column) { 292 double result = 0.0; 293 for (int r = 0; r < dataset.getRowCount(); r++) { 294 Number dataValue = dataset.getValue(r, column); 295 if (dataValue != null) { 296 double v = dataValue.doubleValue(); 297 if (v > 0.0) { 298 result = result + v; 299 } 300 } 301 } 302 return result; 303 } 304 305 313 private double calculateSumOfNegativeValuesForCategory(CategoryDataset dataset, int column) { 314 double result = 0.0; 315 for (int r = 0; r < dataset.getRowCount(); r++) { 316 Number dataValue = dataset.getValue(r, column); 317 if (dataValue != null) { 318 double v = dataValue.doubleValue(); 319 if (v < 0.0) { 320 result = result + v; 321 } 322 } 323 } 324 return result; 325 } 326 327 } 328 | Popular Tags |