/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the plot is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot (<code>null</code> permitted). * @param pass the pass index. */ public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { if (!(dataset instanceof IntervalXYDataset && dataset instanceof TableXYDataset)) { String message = "dataset (type " + dataset.getClass().getName() + ") has wrong type:"; boolean and = false; if (!IntervalXYDataset.class.isAssignableFrom(dataset.getClass())) { message += " it is no IntervalXYDataset"; and = true; } if (!TableXYDataset.class.isAssignableFrom(dataset.getClass())) { if (and) { message += " and"; } message += " it is no TableXYDataset"; } throw new IllegalArgumentException(message); } IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset; double value = intervalDataset.getYValue(series, item); if (Double.isNaN(value)) { return; } // if we are rendering the values as percentages, we need to calculate // the total for the current item. Unfortunately here we end up // repeating the calculation more times than is strictly necessary - // hopefully I'll come back to this and find a way to add the // total(s) to the renderer state. The other problem is we implicitly // assume the dataset has no negative values...perhaps that can be // fixed too. double total = 0.0; if (this.renderAsPercentages) { total = DatasetUtilities.calculateStackTotal((TableXYDataset) dataset, item); value = value / total; } double positiveBase = 0.0; double negativeBase = 0.0; for (int i = 0; i < series; i++) { double v = dataset.getYValue(i, item); if (!Double.isNaN(v)) { if (this.renderAsPercentages) { v = v / total; } if (v > 0) { positiveBase = positiveBase + v; } else { negativeBase = negativeBase + v; } } } double translatedBase; double translatedValue; RectangleEdge edgeR = plot.getRangeAxisEdge(); if (value > 0.0) { translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea, edgeR); translatedValue = rangeAxis.valueToJava2D(positiveBase + value, dataArea, edgeR); } else { translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea, edgeR); translatedValue = rangeAxis.valueToJava2D(negativeBase + value, dataArea, edgeR); } RectangleEdge edgeD = plot.getDomainAxisEdge(); double startX = intervalDataset.getStartXValue(series, item); if (Double.isNaN(startX)) { return; } double translatedStartX = domainAxis.valueToJava2D(startX, dataArea, edgeD); double endX = intervalDataset.getEndXValue(series, item); if (Double.isNaN(endX)) { return; } double translatedEndX = domainAxis.valueToJava2D(endX, dataArea, edgeD); double translatedWidth = Math.max(1, Math.abs(translatedEndX - translatedStartX)); double translatedHeight = Math.abs(translatedValue - translatedBase); if (getMargin() > 0.0) { double cut = translatedWidth * getMargin(); translatedWidth = translatedWidth - cut; translatedStartX = translatedStartX + cut / 2; } Rectangle2D bar = null; PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { bar = new Rectangle2D.Double( Math.min(translatedBase, translatedValue), Math.min(translatedEndX, translatedStartX), translatedHeight, translatedWidth); } else if (orientation == PlotOrientation.VERTICAL) { bar = new Rectangle2D.Double( Math.min(translatedStartX, translatedEndX), Math.min(translatedBase, translatedValue), translatedWidth, translatedHeight); } boolean positive = (value > 0.0); boolean inverted = rangeAxis.isInverted(); RectangleEdge barBase; if (orientation == PlotOrientation.HORIZONTAL) { if (positive && inverted || !positive && !inverted) { barBase = RectangleEdge.RIGHT; } else { barBase = RectangleEdge.LEFT; } } else { if (positive && !inverted || !positive && inverted) { barBase = RectangleEdge.BOTTOM; } else { barBase = RectangleEdge.TOP; } } if (pass == 0) { if (getShadowsVisible()) { getBarPainter().paintBarShadow(g2, this, series, item, bar, barBase, false); } } else if (pass == 1) { getBarPainter().paintBar(g2, this, series, item, bar, barBase); // add an entity for the item... if (info != null) { EntityCollection entities = info.getOwner().getEntityCollection(); if (entities != null) { addEntity(entities, bar, dataset, series, item, bar.getCenterX(), bar.getCenterY()); } } } else if (pass == 2) { // handle item label drawing, now that we know all the bars have // been drawn... if (isItemLabelVisible(series, item)) { XYItemLabelGenerator generator = getItemLabelGenerator(series, item); drawItemLabel(g2, dataset, series, item, plot, generator, bar, value < 0.0); } } }