Beispiel #1
0
  /**
   * 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} permitted).
   * @param pass the pass index.
   */
  @Override
  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 (!getItemVisible(series, item)) {
      return;
    }
    IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset;

    double value0;
    double value1;
    if (this.useYInterval) {
      value0 = intervalDataset.getStartYValue(series, item);
      value1 = intervalDataset.getEndYValue(series, item);
    } else {
      value0 = this.base;
      value1 = intervalDataset.getYValue(series, item);
    }
    if (Double.isNaN(value0) || Double.isNaN(value1)) {
      return;
    }
    if (value0 <= value1) {
      if (!rangeAxis.getRange().intersects(value0, value1)) {
        return;
      }
    } else {
      if (!rangeAxis.getRange().intersects(value1, value0)) {
        return;
      }
    }

    double translatedValue0 = rangeAxis.valueToJava2D(value0, dataArea, plot.getRangeAxisEdge());
    double translatedValue1 = rangeAxis.valueToJava2D(value1, dataArea, plot.getRangeAxisEdge());
    double bottom = Math.min(translatedValue0, translatedValue1);
    double top = Math.max(translatedValue0, translatedValue1);

    double startX = intervalDataset.getStartXValue(series, item);
    if (Double.isNaN(startX)) {
      return;
    }
    double endX = intervalDataset.getEndXValue(series, item);
    if (Double.isNaN(endX)) {
      return;
    }
    if (startX <= endX) {
      if (!domainAxis.getRange().intersects(startX, endX)) {
        return;
      }
    } else {
      if (!domainAxis.getRange().intersects(endX, startX)) {
        return;
      }
    }

    // is there an alignment adjustment to be made?
    if (this.barAlignmentFactor >= 0.0 && this.barAlignmentFactor <= 1.0) {
      double x = intervalDataset.getXValue(series, item);
      double interval = endX - startX;
      startX = x - interval * this.barAlignmentFactor;
      endX = startX + interval;
    }

    RectangleEdge location = plot.getDomainAxisEdge();
    double translatedStartX = domainAxis.valueToJava2D(startX, dataArea, location);
    double translatedEndX = domainAxis.valueToJava2D(endX, dataArea, location);

    double translatedWidth = Math.max(1, Math.abs(translatedEndX - translatedStartX));

    double left = Math.min(translatedStartX, translatedEndX);
    if (getMargin() > 0.0) {
      double cut = translatedWidth * getMargin();
      translatedWidth = translatedWidth - cut;
      left = left + cut / 2;
    }

    Rectangle2D bar = null;
    PlotOrientation orientation = plot.getOrientation();
    if (orientation.isHorizontal()) {
      // clip left and right bounds to data area
      bottom = Math.max(bottom, dataArea.getMinX());
      top = Math.min(top, dataArea.getMaxX());
      bar = new Rectangle2D.Double(bottom, left, top - bottom, translatedWidth);
    } else if (orientation.isVertical()) {
      // clip top and bottom bounds to data area
      bottom = Math.max(bottom, dataArea.getMinY());
      top = Math.min(top, dataArea.getMaxY());
      bar = new Rectangle2D.Double(left, bottom, translatedWidth, top - bottom);
    }

    boolean positive = (value1 > 0.0);
    boolean inverted = rangeAxis.isInverted();
    RectangleEdge barBase;
    if (orientation.isHorizontal()) {
      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 (state.getElementHinting()) {
      beginElementGroup(g2, dataset.getSeriesKey(series), item);
    }
    if (getShadowsVisible()) {
      this.barPainter.paintBarShadow(g2, this, series, item, bar, barBase, !this.useYInterval);
    }
    this.barPainter.paintBar(g2, this, series, item, bar, barBase);
    if (state.getElementHinting()) {
      endElementGroup(g2);
    }

    if (isItemLabelVisible(series, item)) {
      XYItemLabelGenerator generator = getItemLabelGenerator(series, item);
      drawItemLabel(g2, dataset, series, item, plot, generator, bar, value1 < 0.0);
    }

    // update the crosshair point
    double x1 = (startX + endX) / 2.0;
    double y1 = dataset.getYValue(series, item);
    double transX1 = domainAxis.valueToJava2D(x1, dataArea, location);
    double transY1 = rangeAxis.valueToJava2D(y1, dataArea, plot.getRangeAxisEdge());
    int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
    int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
    updateCrosshairValues(
        crosshairState,
        x1,
        y1,
        domainAxisIndex,
        rangeAxisIndex,
        transX1,
        transY1,
        plot.getOrientation());

    EntityCollection entities = state.getEntityCollection();
    if (entities != null) {
      addEntity(entities, bar, dataset, series, item, 0.0, 0.0);
    }
  }
  /**
   * 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);
      }
    }
  }