/**
   * Draws a grid line against the range axis.
   *
   * @param g2 the graphics device.
   * @param plot the plot.
   * @param axis the value axis.
   * @param dataArea the area for plotting data (not yet adjusted for any 3D effect).
   * @param value the value at which the grid line should be drawn.
   */
  public void drawRangeGridline(
      Graphics2D g2, CategoryPlot plot, ValueAxis axis, Rectangle2D dataArea, double value) {

    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);
    }

    Paint paint = plot.getRangeGridlinePaint();
    if (paint == null) {
      paint = CategoryPlot.DEFAULT_GRIDLINE_PAINT;
    }
    g2.setPaint(paint);

    Stroke stroke = plot.getRangeGridlineStroke();
    if (stroke == null) {
      stroke = CategoryPlot.DEFAULT_GRIDLINE_STROKE;
    }
    g2.setStroke(stroke);

    g2.draw(line);
  }
  /** Replaces the dataset and checks that the data range is as expected. */
  public void testReplaceDataset() {

    // create a dataset...
    Number[][] data =
        new Integer[][] {
          {new Integer(-30), new Integer(-20)},
          {new Integer(-10), new Integer(10)},
          {new Integer(20), new Integer(30)}
        };

    CategoryDataset newData = DatasetUtilities.createCategoryDataset("S", "C", data);

    LocalListener l = new LocalListener();
    this.chart.addChangeListener(l);
    this.chart.getCategoryPlot().setDataset(newData);
    assertEquals(true, l.flag);
    ValueAxis axis = this.chart.getCategoryPlot().getRangeAxis();
    Range range = axis.getRange();
    assertTrue(
        "Expecting the lower bound of the range to be around -30: " + range.getLowerBound(),
        range.getLowerBound() <= -30);
    assertTrue(
        "Expecting the upper bound of the range to be around 30: " + range.getUpperBound(),
        range.getUpperBound() >= 30);
  }
 public void stateChanged(ChangeEvent changeevent) {
   int i = slider.getValue();
   XYPlot xyplot = (XYPlot) chart.getPlot();
   ValueAxis valueaxis = xyplot.getDomainAxis();
   Range range = valueaxis.getRange();
   double d = valueaxis.getLowerBound() + ((double) i / 100D) * range.getLength();
   xyplot.setDomainCrosshairValue(d);
 }
 /**
  * Handles a state change event.
  *
  * @param event the event.
  */
 public void stateChanged(ChangeEvent event) {
   int value = this.slider.getValue();
   XYPlot plot = this.chart.getXYPlot();
   ValueAxis domainAxis = plot.getDomainAxis();
   Range range = domainAxis.getRange();
   double c = domainAxis.getLowerBound() + (value / 100.0) * range.getLength();
   plot.setDomainCrosshairValue(c);
 }
Beispiel #5
0
  /**
   * Draws a range marker.
   *
   * @param g2 the graphics device.
   * @param plot the plot.
   * @param axis the value axis.
   * @param marker the marker.
   * @param dataArea the area for plotting data (not including 3D effect).
   */
  @Override
  public void drawRangeMarker(
      Graphics2D g2, CategoryPlot plot, ValueAxis axis, Marker marker, Rectangle2D dataArea) {

    Rectangle2D adjusted =
        new Rectangle2D.Double(
            dataArea.getX(),
            dataArea.getY() + getYOffset(),
            dataArea.getWidth() - getXOffset(),
            dataArea.getHeight() - getYOffset());

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

      GeneralPath path = null;
      PlotOrientation orientation = plot.getOrientation();
      if (orientation == PlotOrientation.HORIZONTAL) {
        float x = (float) axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge());
        float y = (float) adjusted.getMaxY();
        path = new GeneralPath();
        path.moveTo(x, y);
        path.lineTo((float) (x + getXOffset()), y - (float) getYOffset());
        path.lineTo((float) (x + getXOffset()), (float) (adjusted.getMinY() - getYOffset()));
        path.lineTo(x, (float) adjusted.getMinY());
        path.closePath();
      } else if (orientation == PlotOrientation.VERTICAL) {
        float y = (float) axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge());
        float x = (float) dataArea.getX();
        path = new GeneralPath();
        path.moveTo(x, y);
        path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset);
        path.lineTo((float) (adjusted.getMaxX() + this.xOffset), y - (float) this.yOffset);
        path.lineTo((float) (adjusted.getMaxX()), y);
        path.closePath();
      }
      g2.setPaint(marker.getPaint());
      g2.fill(path);
      g2.setPaint(marker.getOutlinePaint());
      g2.draw(path);
    } else {
      super.drawRangeMarker(g2, plot, axis, marker, adjusted);
      // TODO: draw the interval marker with a 3D effect
    }
  }
 private void finishScalingUpdate(
     AxisRangeControl axisRangeControl, ValueAxis newAxis, ValueAxis oldAxis) {
   if (axisRangeControl.isAutoMinMax()) {
     newAxis.setAutoRange(false);
     acceptableDeviationDataset.removeAllSeries();
     regressionDataset.removeAllSeries();
     getPlot().removeAnnotation(r2Annotation);
     newAxis.setAutoRange(true);
     axisRangeControl.adjustComponents(newAxis, 3);
     newAxis.setAutoRange(false);
     computeRegressionAndAcceptableDeviationData();
   } else {
     newAxis.setAutoRange(false);
     newAxis.setRange(oldAxis.getRange());
   }
 }
  /**
   * Draws a line perpendicular to the range axis.
   *
   * @param g2 the graphics device.
   * @param plot the plot.
   * @param axis the value axis.
   * @param dataArea the area for plotting data (not yet adjusted for any 3D effect).
   * @param value the value at which the grid line should be drawn.
   * @param paint the paint.
   * @param stroke the stroke.
   * @see #drawRangeGridline
   * @since 1.0.13
   */
  public void drawRangeLine(
      Graphics2D g2,
      CategoryPlot plot,
      ValueAxis axis,
      Rectangle2D dataArea,
      double value,
      Paint paint,
      Stroke stroke) {

    Range range = axis.getRange();
    if (!range.contains(value)) {
      return;
    }

    Rectangle2D adjusted =
        new Rectangle2D.Double(
            dataArea.getX(),
            dataArea.getY() + getYOffset(),
            dataArea.getWidth() - getXOffset(),
            dataArea.getHeight() - getYOffset());

    Line2D line1 = null;
    Line2D line2 = null;
    PlotOrientation orientation = plot.getOrientation();
    if (orientation == PlotOrientation.HORIZONTAL) {
      double x0 = axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge());
      double x1 = x0 + getXOffset();
      double y0 = dataArea.getMaxY();
      double y1 = y0 - getYOffset();
      double y2 = dataArea.getMinY();
      line1 = new Line2D.Double(x0, y0, x1, y1);
      line2 = new Line2D.Double(x1, y1, x1, y2);
    } else if (orientation == PlotOrientation.VERTICAL) {
      double y0 = axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge());
      double y1 = y0 - getYOffset();
      double x0 = dataArea.getMinX();
      double x1 = x0 + getXOffset();
      double x2 = dataArea.getMaxX();
      line1 = new Line2D.Double(x0, y0, x1, y1);
      line2 = new Line2D.Double(x1, y1, x2, y1);
    }
    g2.setPaint(paint);
    g2.setStroke(stroke);
    g2.draw(line1);
    g2.draw(line2);
  }
  /** Replaces the dataset and checks that it has changed as expected. */
  public void testReplaceDataset() {

    // create a dataset...
    XYSeries series1 = new XYSeries("Series 1");
    series1.add(10.0, 10.0);
    series1.add(20.0, 20.0);
    series1.add(30.0, 30.0);
    XYDataset dataset = new XYSeriesCollection(series1);

    LocalListener l = new LocalListener();
    this.chart.addChangeListener(l);
    XYPlot plot = (XYPlot) this.chart.getPlot();
    plot.setDataset(dataset);
    assertEquals(true, l.flag);
    ValueAxis axis = plot.getRangeAxis();
    Range range = axis.getRange();
    assertTrue(
        "Expecting the lower bound of the range to be around 10: " + range.getLowerBound(),
        range.getLowerBound() <= 10);
    assertTrue(
        "Expecting the upper bound of the range to be around 30: " + range.getUpperBound(),
        range.getUpperBound() >= 30);
  }
  /**
   * Draw a single data item.
   *
   * @param g2 the graphics device.
   * @param state the renderer state.
   * @param dataArea the area in which the data is drawn.
   * @param plot the plot.
   * @param domainAxis the domain axis.
   * @param rangeAxis the range axis.
   * @param dataset the dataset (a {@link StatisticalCategoryDataset} is required).
   * @param row the row index (zero-based).
   * @param column the column index (zero-based).
   * @param pass the pass.
   */
  @Override
  public void drawItem(
      Graphics2D g2,
      CategoryItemRendererState state,
      Rectangle2D dataArea,
      CategoryPlot plot,
      CategoryAxis domainAxis,
      ValueAxis rangeAxis,
      CategoryDataset dataset,
      int row,
      int column,
      int pass) {

    // do nothing if item is not visible
    if (!getItemVisible(row, column)) {
      return;
    }

    // if the dataset is not a StatisticalCategoryDataset then just revert
    // to the superclass (LineAndShapeRenderer) behaviour...
    if (!(dataset instanceof StatisticalCategoryDataset)) {
      super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis, dataset, row, column, pass);
      return;
    }

    int visibleRow = state.getVisibleSeriesIndex(row);
    if (visibleRow < 0) {
      return;
    }
    int visibleRowCount = state.getVisibleSeriesCount();

    StatisticalCategoryDataset statDataset = (StatisticalCategoryDataset) dataset;
    Number meanValue = statDataset.getMeanValue(row, column);
    if (meanValue == null) {
      return;
    }
    PlotOrientation orientation = plot.getOrientation();

    // current data point...
    double x1;
    if (getUseSeriesOffset()) {
      x1 =
          domainAxis.getCategorySeriesMiddle(
              column,
              dataset.getColumnCount(),
              visibleRow,
              visibleRowCount,
              getItemMargin(),
              dataArea,
              plot.getDomainAxisEdge());
    } else {
      x1 =
          domainAxis.getCategoryMiddle(
              column, getColumnCount(), dataArea, plot.getDomainAxisEdge());
    }
    double y1 = rangeAxis.valueToJava2D(meanValue.doubleValue(), dataArea, plot.getRangeAxisEdge());

    // draw the standard deviation lines *before* the shapes (if they're
    // visible) - it looks better if the shape fill colour is different to
    // the line colour
    Number sdv = statDataset.getStdDevValue(row, column);
    if (pass == 1 && sdv != null) {
      // standard deviation lines
      RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
      double valueDelta = sdv.doubleValue();
      double highVal, lowVal;
      if ((meanValue.doubleValue() + valueDelta) > rangeAxis.getRange().getUpperBound()) {
        highVal =
            rangeAxis.valueToJava2D(rangeAxis.getRange().getUpperBound(), dataArea, yAxisLocation);
      } else {
        highVal =
            rangeAxis.valueToJava2D(meanValue.doubleValue() + valueDelta, dataArea, yAxisLocation);
      }

      if ((meanValue.doubleValue() + valueDelta) < rangeAxis.getRange().getLowerBound()) {
        lowVal =
            rangeAxis.valueToJava2D(rangeAxis.getRange().getLowerBound(), dataArea, yAxisLocation);
      } else {
        lowVal =
            rangeAxis.valueToJava2D(meanValue.doubleValue() - valueDelta, dataArea, yAxisLocation);
      }

      if (this.errorIndicatorPaint != null) {
        g2.setPaint(this.errorIndicatorPaint);
      } else {
        g2.setPaint(getItemPaint(row, column));
      }
      if (this.errorIndicatorStroke != null) {
        g2.setStroke(this.errorIndicatorStroke);
      } else {
        g2.setStroke(getItemOutlineStroke(row, column));
      }
      Line2D line = new Line2D.Double();
      if (orientation == PlotOrientation.HORIZONTAL) {
        line.setLine(lowVal, x1, highVal, x1);
        g2.draw(line);
        line.setLine(lowVal, x1 - 5.0d, lowVal, x1 + 5.0d);
        g2.draw(line);
        line.setLine(highVal, x1 - 5.0d, highVal, x1 + 5.0d);
        g2.draw(line);
      } else { // PlotOrientation.VERTICAL
        line.setLine(x1, lowVal, x1, highVal);
        g2.draw(line);
        line.setLine(x1 - 5.0d, highVal, x1 + 5.0d, highVal);
        g2.draw(line);
        line.setLine(x1 - 5.0d, lowVal, x1 + 5.0d, lowVal);
        g2.draw(line);
      }
    }

    Shape hotspot = null;
    if (pass == 1 && getItemShapeVisible(row, column)) {
      Shape shape = getItemShape(row, column);
      if (orientation == PlotOrientation.HORIZONTAL) {
        shape = ShapeUtilities.createTranslatedShape(shape, y1, x1);
      } else if (orientation == PlotOrientation.VERTICAL) {
        shape = ShapeUtilities.createTranslatedShape(shape, x1, y1);
      }
      hotspot = shape;

      if (getItemShapeFilled(row, column)) {
        if (getUseFillPaint()) {
          g2.setPaint(getItemFillPaint(row, column));
        } else {
          g2.setPaint(getItemPaint(row, column));
        }
        g2.fill(shape);
      }
      if (getDrawOutlines()) {
        if (getUseOutlinePaint()) {
          g2.setPaint(getItemOutlinePaint(row, column));
        } else {
          g2.setPaint(getItemPaint(row, column));
        }
        g2.setStroke(getItemOutlineStroke(row, column));
        g2.draw(shape);
      }
      // draw the item label if there is one...
      if (isItemLabelVisible(row, column)) {
        if (orientation == PlotOrientation.HORIZONTAL) {
          drawItemLabel(
              g2, orientation, dataset, row, column, y1, x1, (meanValue.doubleValue() < 0.0));
        } else if (orientation == PlotOrientation.VERTICAL) {
          drawItemLabel(
              g2, orientation, dataset, row, column, x1, y1, (meanValue.doubleValue() < 0.0));
        }
      }
    }

    if (pass == 0 && getItemLineVisible(row, column)) {
      if (column != 0) {

        Number previousValue = statDataset.getValue(row, column - 1);
        if (previousValue != null) {

          // previous data point...
          double previous = previousValue.doubleValue();
          double x0;
          if (getUseSeriesOffset()) {
            x0 =
                domainAxis.getCategorySeriesMiddle(
                    column - 1,
                    dataset.getColumnCount(),
                    visibleRow,
                    visibleRowCount,
                    getItemMargin(),
                    dataArea,
                    plot.getDomainAxisEdge());
          } else {
            x0 =
                domainAxis.getCategoryMiddle(
                    column - 1, getColumnCount(), dataArea, plot.getDomainAxisEdge());
          }
          double y0 = rangeAxis.valueToJava2D(previous, dataArea, plot.getRangeAxisEdge());

          Line2D line = null;
          if (orientation == PlotOrientation.HORIZONTAL) {
            line = new Line2D.Double(y0, x0, y1, x1);
          } else if (orientation == PlotOrientation.VERTICAL) {
            line = new Line2D.Double(x0, y0, x1, y1);
          }
          g2.setPaint(getItemPaint(row, column));
          g2.setStroke(getItemStroke(row, column));
          g2.draw(line);
        }
      }
    }

    if (pass == 1) {
      // add an item entity, if this information is being collected
      EntityCollection entities = state.getEntityCollection();
      if (entities != null) {
        addEntity(entities, hotspot, dataset, row, column, x1, y1);
      }
    }
  }
Beispiel #10
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.
   */
  @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) {

    double x = dataset.getXValue(series, item);
    if (!domainAxis.getRange().contains(x)) {
      return; // the x value is not within the axis range
    }
    double xx = domainAxis.valueToJava2D(x, dataArea, plot.getDomainAxisEdge());

    // setup for collecting optional entity info...
    Shape entityArea = null;
    EntityCollection entities = null;
    if (info != null) {
      entities = info.getOwner().getEntityCollection();
    }

    PlotOrientation orientation = plot.getOrientation();
    RectangleEdge location = plot.getRangeAxisEdge();

    Paint itemPaint = getItemPaint(series, item);
    Stroke itemStroke = getItemStroke(series, item);
    g2.setPaint(itemPaint);
    g2.setStroke(itemStroke);

    if (dataset instanceof OHLCDataset) {
      OHLCDataset hld = (OHLCDataset) dataset;

      double yHigh = hld.getHighValue(series, item);
      double yLow = hld.getLowValue(series, item);
      if (!Double.isNaN(yHigh) && !Double.isNaN(yLow)) {
        double yyHigh = rangeAxis.valueToJava2D(yHigh, dataArea, location);
        double yyLow = rangeAxis.valueToJava2D(yLow, dataArea, location);
        if (orientation == PlotOrientation.HORIZONTAL) {
          g2.draw(new Line2D.Double(yyLow, xx, yyHigh, xx));
          entityArea =
              new Rectangle2D.Double(
                  Math.min(yyLow, yyHigh), xx - 1.0, Math.abs(yyHigh - yyLow), 2.0);
        } else if (orientation == PlotOrientation.VERTICAL) {
          g2.draw(new Line2D.Double(xx, yyLow, xx, yyHigh));
          entityArea =
              new Rectangle2D.Double(
                  xx - 1.0, Math.min(yyLow, yyHigh), 2.0, Math.abs(yyHigh - yyLow));
        }
      }

      double delta = getTickLength();
      if (domainAxis.isInverted()) {
        delta = -delta;
      }
      if (getDrawOpenTicks()) {
        double yOpen = hld.getOpenValue(series, item);
        if (!Double.isNaN(yOpen)) {
          double yyOpen = rangeAxis.valueToJava2D(yOpen, dataArea, location);
          if (this.openTickPaint != null) {
            g2.setPaint(this.openTickPaint);
          } else {
            g2.setPaint(itemPaint);
          }
          if (orientation == PlotOrientation.HORIZONTAL) {
            g2.draw(new Line2D.Double(yyOpen, xx + delta, yyOpen, xx));
          } else if (orientation == PlotOrientation.VERTICAL) {
            g2.draw(new Line2D.Double(xx - delta, yyOpen, xx, yyOpen));
          }
        }
      }

      if (getDrawCloseTicks()) {
        double yClose = hld.getCloseValue(series, item);
        if (!Double.isNaN(yClose)) {
          double yyClose = rangeAxis.valueToJava2D(yClose, dataArea, location);
          if (this.closeTickPaint != null) {
            g2.setPaint(this.closeTickPaint);
          } else {
            g2.setPaint(itemPaint);
          }
          if (orientation == PlotOrientation.HORIZONTAL) {
            g2.draw(new Line2D.Double(yyClose, xx, yyClose, xx - delta));
          } else if (orientation == PlotOrientation.VERTICAL) {
            g2.draw(new Line2D.Double(xx, yyClose, xx + delta, yyClose));
          }
        }
      }

    } else {
      // not a HighLowDataset, so just draw a line connecting this point
      // with the previous point...
      if (item > 0) {
        double x0 = dataset.getXValue(series, item - 1);
        double y0 = dataset.getYValue(series, item - 1);
        double y = dataset.getYValue(series, item);
        if (Double.isNaN(x0) || Double.isNaN(y0) || Double.isNaN(y)) {
          return;
        }
        double xx0 = domainAxis.valueToJava2D(x0, dataArea, plot.getDomainAxisEdge());
        double yy0 = rangeAxis.valueToJava2D(y0, dataArea, location);
        double yy = rangeAxis.valueToJava2D(y, dataArea, location);
        if (orientation == PlotOrientation.HORIZONTAL) {
          g2.draw(new Line2D.Double(yy0, xx0, yy, xx));
        } else if (orientation == PlotOrientation.VERTICAL) {
          g2.draw(new Line2D.Double(xx0, yy0, xx, yy));
        }
      }
    }

    if (entities != null) {
      addEntity(entities, entityArea, dataset, series, item, 0.0, 0.0);
    }
  }
  /**
   * Draws a range marker.
   *
   * @param g2 the graphics device.
   * @param plot the plot.
   * @param axis the value axis.
   * @param marker the marker.
   * @param dataArea the area for plotting data (not including 3D effect).
   */
  public void drawRangeMarker(
      Graphics2D g2, CategoryPlot plot, ValueAxis axis, Marker marker, Rectangle2D dataArea) {

    Rectangle2D adjusted =
        new Rectangle2D.Double(
            dataArea.getX(),
            dataArea.getY() + getYOffset(),
            dataArea.getWidth() - getXOffset(),
            dataArea.getHeight() - getYOffset());
    if (marker instanceof ValueMarker) {
      ValueMarker vm = (ValueMarker) marker;
      double value = vm.getValue();
      Range range = axis.getRange();
      if (!range.contains(value)) {
        return;
      }

      GeneralPath path = null;
      PlotOrientation orientation = plot.getOrientation();
      if (orientation == PlotOrientation.HORIZONTAL) {
        float x = (float) axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge());
        float y = (float) adjusted.getMaxY();
        path = new GeneralPath();
        path.moveTo(x, y);
        path.lineTo((float) (x + getXOffset()), y - (float) getYOffset());
        path.lineTo((float) (x + getXOffset()), (float) (adjusted.getMinY() - getYOffset()));
        path.lineTo(x, (float) adjusted.getMinY());
        path.closePath();
      } else if (orientation == PlotOrientation.VERTICAL) {
        float y = (float) axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge());
        float x = (float) dataArea.getX();
        path = new GeneralPath();
        path.moveTo(x, y);
        path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset);
        path.lineTo((float) (adjusted.getMaxX() + this.xOffset), y - (float) this.yOffset);
        path.lineTo((float) (adjusted.getMaxX()), y);
        path.closePath();
      }
      g2.setPaint(marker.getPaint());
      g2.fill(path);
      g2.setPaint(marker.getOutlinePaint());
      g2.draw(path);

      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,
                path.getBounds2D(),
                marker.getLabelOffset(),
                LengthAdjustmentType.EXPAND,
                anchor);
        TextUtilities.drawAlignedString(
            label,
            g2,
            (float) coordinates.getX(),
            (float) coordinates.getY(),
            marker.getLabelTextAnchor());
      }

    } else {
      super.drawRangeMarker(g2, plot, axis, marker, adjusted);
      // TODO: draw the interval marker with a 3D effect
    }
  }
  /**
   * 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());
      }
    }
  }