/**
   * Draws an item for a plot with a vertical orientation.
   *
   * @param g2 the graphics device.
   * @param state the renderer state.
   * @param dataArea the data area.
   * @param plot the plot.
   * @param domainAxis the domain axis.
   * @param rangeAxis the range axis.
   * @param dataset the data.
   * @param visibleRow the visible row index.
   * @param row the row index (zero-based).
   * @param column the column index (zero-based).
   */
  protected void drawVerticalItem(
      Graphics2D g2,
      CategoryItemRendererState state,
      Rectangle2D dataArea,
      CategoryPlot plot,
      CategoryAxis domainAxis,
      ValueAxis rangeAxis,
      StatisticalCategoryDataset dataset,
      int visibleRow,
      int row,
      int column) {

    // BAR X
    double rectX =
        calculateBarW0(
            plot, PlotOrientation.VERTICAL, dataArea, domainAxis, state, visibleRow, column);

    // BAR Y
    Number meanValue = dataset.getMeanValue(row, column);
    if (meanValue == null) {
      return;
    }

    double value = meanValue.doubleValue();
    double base = 0.0;
    double lclip = getLowerClip();
    double uclip = getUpperClip();

    if (uclip <= 0.0) { // cases 1, 2, 3 and 4
      if (value >= uclip) {
        return; // bar is not visible
      }
      base = uclip;
      if (value <= lclip) {
        value = lclip;
      }
    } else if (lclip <= 0.0) { // cases 5, 6, 7 and 8
      if (value >= uclip) {
        value = uclip;
      } else {
        if (value <= lclip) {
          value = lclip;
        }
      }
    } else { // cases 9, 10, 11 and 12
      if (value <= lclip) {
        return; // bar is not visible
      }
      base = getLowerClip();
      if (value >= uclip) {
        value = uclip;
      }
    }

    RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
    double transY1 = rangeAxis.valueToJava2D(base, dataArea, yAxisLocation);
    double transY2 = rangeAxis.valueToJava2D(value, dataArea, yAxisLocation);
    double rectY = Math.min(transY2, transY1);

    double rectWidth = state.getBarWidth();
    double rectHeight = Math.abs(transY2 - transY1);

    Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth, rectHeight);
    Paint itemPaint = getItemPaint(row, column);
    GradientPaintTransformer t = getGradientPaintTransformer();
    if (t != null && itemPaint instanceof GradientPaint) {
      itemPaint = t.transform((GradientPaint) itemPaint, bar);
    }
    g2.setPaint(itemPaint);
    g2.fill(bar);
    // draw the outline...
    if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
      Stroke stroke = getItemOutlineStroke(row, column);
      Paint paint = getItemOutlinePaint(row, column);
      if (stroke != null && paint != null) {
        g2.setStroke(stroke);
        g2.setPaint(paint);
        g2.draw(bar);
      }
    }

    // standard deviation lines
    Number n = dataset.getStdDevValue(row, column);
    if (n != null) {
      double valueDelta = n.doubleValue();
      double highVal =
          rangeAxis.valueToJava2D(meanValue.doubleValue() + valueDelta, dataArea, yAxisLocation);
      double lowVal =
          rangeAxis.valueToJava2D(meanValue.doubleValue() - valueDelta, dataArea, yAxisLocation);

      if (this.errorIndicatorPaint != null) {
        g2.setPaint(this.errorIndicatorPaint);
      } else {
        g2.setPaint(getItemOutlinePaint(row, column));
      }
      if (this.errorIndicatorStroke != null) {
        g2.setStroke(this.errorIndicatorStroke);
      } else {
        g2.setStroke(getItemOutlineStroke(row, column));
      }

      Line2D line;
      line =
          new Line2D.Double(
              rectX + rectWidth / 2.0d, lowVal,
              rectX + rectWidth / 2.0d, highVal);
      g2.draw(line);
      line =
          new Line2D.Double(
              rectX + rectWidth / 2.0d - 5.0d, highVal, rectX + rectWidth / 2.0d + 5.0d, highVal);
      g2.draw(line);
      line =
          new Line2D.Double(
              rectX + rectWidth / 2.0d - 5.0d, lowVal, rectX + rectWidth / 2.0d + 5.0d, lowVal);
      g2.draw(line);
    }

    CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column);
    if (generator != null && isItemLabelVisible(row, column)) {
      drawItemLabel(g2, dataset, row, column, plot, generator, bar, (value < 0.0));
    }

    // add an item entity, if this information is being collected
    EntityCollection entities = state.getEntityCollection();
    if (entities != null) {
      addItemEntity(entities, dataset, row, column, bar);
    }
  }
  /**
   * Draws a marker for the range axis.
   *
   * @param g2 the graphics device (not <code>null</code>).
   * @param plot the plot (not <code>null</code>).
   * @param axis the range axis (not <code>null</code>).
   * @param marker the marker to be drawn (not <code>null</code>).
   * @param dataArea the area inside the axes (not <code>null</code>).
   */
  public void drawRangeMarker(
      Graphics2D g2, CategoryPlot plot, ValueAxis axis, Marker marker, Rectangle2D dataArea) {

    if (marker instanceof ValueMarker) {
      ValueMarker vm = (ValueMarker) marker;
      double value = vm.getValue();
      Range range = axis.getRange();

      if (!range.contains(value)) {
        return;
      }

      PlotOrientation orientation = plot.getOrientation();
      double v = axis.valueToJava2D(value, dataArea, plot.getRangeAxisEdge());
      Line2D line = null;
      if (orientation == PlotOrientation.HORIZONTAL) {
        line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea.getMaxY());
      } else if (orientation == PlotOrientation.VERTICAL) {
        line = new Line2D.Double(dataArea.getMinX(), v, dataArea.getMaxX(), v);
      }

      g2.setPaint(marker.getPaint());
      g2.setStroke(marker.getStroke());
      g2.draw(line);

      String label = marker.getLabel();
      RectangleAnchor anchor = marker.getLabelAnchor();
      if (label != null) {
        Font labelFont = marker.getLabelFont();
        g2.setFont(labelFont);
        g2.setPaint(marker.getLabelPaint());
        Point2D coordinates =
            calculateRangeMarkerTextAnchorPoint(
                g2,
                orientation,
                dataArea,
                line.getBounds2D(),
                marker.getLabelOffset(),
                LengthAdjustmentType.EXPAND,
                anchor);
        TextUtilities.drawAlignedString(
            label,
            g2,
            (float) coordinates.getX(),
            (float) coordinates.getY(),
            marker.getLabelTextAnchor());
      }
    } else if (marker instanceof IntervalMarker) {

      IntervalMarker im = (IntervalMarker) marker;
      double start = im.getStartValue();
      double end = im.getEndValue();
      Range range = axis.getRange();
      if (!(range.intersects(start, end))) {
        return;
      }

      // don't draw beyond the axis range...
      start = range.constrain(start);
      end = range.constrain(end);

      double v0 = axis.valueToJava2D(start, dataArea, plot.getRangeAxisEdge());
      double v1 = axis.valueToJava2D(end, dataArea, plot.getRangeAxisEdge());

      PlotOrientation orientation = plot.getOrientation();
      Rectangle2D rect = null;
      if (orientation == PlotOrientation.HORIZONTAL) {
        rect = new Rectangle2D.Double(v0, dataArea.getMinY(), v1 - v0, dataArea.getHeight());
      } else if (orientation == PlotOrientation.VERTICAL) {
        rect =
            new Rectangle2D.Double(
                dataArea.getMinX(), Math.min(v0, v1),
                dataArea.getWidth(), Math.abs(v1 - v0));
      }
      Paint p = marker.getPaint();
      if (p instanceof GradientPaint) {
        GradientPaint gp = (GradientPaint) p;
        GradientPaintTransformer t = im.getGradientPaintTransformer();
        if (t != null) {
          gp = t.transform(gp, rect);
        }
        g2.setPaint(gp);
      } else {
        g2.setPaint(p);
      }
      g2.fill(rect);

      String label = marker.getLabel();
      RectangleAnchor anchor = marker.getLabelAnchor();
      if (label != null) {
        Font labelFont = marker.getLabelFont();
        g2.setFont(labelFont);
        g2.setPaint(marker.getLabelPaint());
        Point2D coordinates =
            calculateRangeMarkerTextAnchorPoint(
                g2,
                orientation,
                dataArea,
                rect,
                marker.getLabelOffset(),
                marker.getLabelOffsetType(),
                anchor);
        TextUtilities.drawAlignedString(
            label,
            g2,
            (float) coordinates.getX(),
            (float) coordinates.getY(),
            marker.getLabelTextAnchor());
      }
    }
  }