/**
   * Draws the tick marks. This method is called during chart rendering, you normally would not call
   * this method yourself.
   *
   * @param g2 the graphics target ({@code null} not permitted)
   * @param cursor the current offset from the edge of the dataArea
   * @param dataArea the area used for plotting data ({@code null} not permitted)
   * @param edge the location of the axis ({@code null} not permitted)
   * @param state axis state information ({@code null} not permitted)
   * @since 1.0.13
   */
  public void drawTickMarks(
      Graphics2D g2, double cursor, Rectangle2D dataArea, RectangleEdge edge, AxisState state) {

    Plot p = getPlot();
    if (p == null) {
      return;
    }
    CategoryPlot plot = (CategoryPlot) p;
    double il = getTickMarkInsideLength();
    double ol = getTickMarkOutsideLength();
    Line2D line = new Line2D.Double();
    List<Comparable> categories = plot.getCategoriesForAxis(this);
    g2.setPaint(getTickMarkPaint());
    g2.setStroke(getTickMarkStroke());
    if (edge.equals(RectangleEdge.TOP)) {
      for (Comparable key : categories) {
        double x = getCategoryMiddle(key, categories, dataArea, edge);
        line.setLine(x, cursor, x, cursor + il);
        g2.draw(line);
        line.setLine(x, cursor, x, cursor - ol);
        g2.draw(line);
      }
      state.cursorUp(ol);
    } else if (edge.equals(RectangleEdge.BOTTOM)) {
      for (Comparable key : categories) {
        double x = getCategoryMiddle(key, categories, dataArea, edge);
        line.setLine(x, cursor, x, cursor - il);
        g2.draw(line);
        line.setLine(x, cursor, x, cursor + ol);
        g2.draw(line);
      }
      state.cursorDown(ol);
    } else if (edge.equals(RectangleEdge.LEFT)) {
      for (Comparable key : categories) {
        double y = getCategoryMiddle(key, categories, dataArea, edge);
        line.setLine(cursor, y, cursor + il, y);
        g2.draw(line);
        line.setLine(cursor, y, cursor - ol, y);
        g2.draw(line);
      }
      state.cursorLeft(ol);
    } else if (edge.equals(RectangleEdge.RIGHT)) {
      for (Comparable key : categories) {
        double y = getCategoryMiddle(key, categories, dataArea, edge);
        line.setLine(cursor, y, cursor - il, y);
        g2.draw(line);
        line.setLine(cursor, y, cursor + ol, y);
        g2.draw(line);
      }
      state.cursorRight(ol);
    }
  }
  /**
   * Draws the axis label.
   *
   * @param label the label text.
   * @param g2 the graphics device.
   * @param plotArea the plot area.
   * @param dataArea the area inside the axes.
   * @param edge the location of the axis.
   * @param state the axis state (<code>null</code> not permitted).
   * @return Information about the axis.
   */
  protected AxisState drawLabel(
      String label,
      Graphics2D g2,
      Rectangle2D plotArea,
      Rectangle2D dataArea,
      RectangleEdge edge,
      AxisState state) {

    // it is unlikely that 'state' will be null, but check anyway...
    ParamChecks.nullNotPermitted(state, "state");

    if ((label == null) || (label.equals(""))) {
      return state;
    }

    Font font = getLabelFont();
    RectangleInsets insets = getLabelInsets();
    g2.setFont(font);
    g2.setPaint(getLabelPaint());
    FontMetrics fm = g2.getFontMetrics();
    Rectangle2D labelBounds = TextUtilities.getTextBounds(label, g2, fm);

    if (edge == RectangleEdge.TOP) {
      AffineTransform t =
          AffineTransform.getRotateInstance(
              getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY());
      Shape rotatedLabelBounds = t.createTransformedShape(labelBounds);
      labelBounds = rotatedLabelBounds.getBounds2D();
      double labelx = dataArea.getCenterX();
      double labely = state.getCursor() - insets.getBottom() - labelBounds.getHeight() / 2.0;
      TextUtilities.drawRotatedString(
          label,
          g2,
          (float) labelx,
          (float) labely,
          TextAnchor.CENTER,
          getLabelAngle(),
          TextAnchor.CENTER);
      state.cursorUp(insets.getTop() + labelBounds.getHeight() + insets.getBottom());
    } else if (edge == RectangleEdge.BOTTOM) {
      AffineTransform t =
          AffineTransform.getRotateInstance(
              getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY());
      Shape rotatedLabelBounds = t.createTransformedShape(labelBounds);
      labelBounds = rotatedLabelBounds.getBounds2D();
      double labelx = dataArea.getCenterX();
      double labely = state.getCursor() + insets.getTop() + labelBounds.getHeight() / 2.0;
      TextUtilities.drawRotatedString(
          label,
          g2,
          (float) labelx,
          (float) labely,
          TextAnchor.CENTER,
          getLabelAngle(),
          TextAnchor.CENTER);
      state.cursorDown(insets.getTop() + labelBounds.getHeight() + insets.getBottom());
    } else if (edge == RectangleEdge.LEFT) {
      AffineTransform t =
          AffineTransform.getRotateInstance(
              getLabelAngle() - Math.PI / 2.0, labelBounds.getCenterX(), labelBounds.getCenterY());
      Shape rotatedLabelBounds = t.createTransformedShape(labelBounds);
      labelBounds = rotatedLabelBounds.getBounds2D();
      double labelx = state.getCursor() - insets.getRight() - labelBounds.getWidth() / 2.0;
      double labely = dataArea.getCenterY();
      TextUtilities.drawRotatedString(
          label,
          g2,
          (float) labelx,
          (float) labely,
          TextAnchor.CENTER,
          getLabelAngle() - Math.PI / 2.0,
          TextAnchor.CENTER);
      state.cursorLeft(insets.getLeft() + labelBounds.getWidth() + insets.getRight());
    } else if (edge == RectangleEdge.RIGHT) {

      AffineTransform t =
          AffineTransform.getRotateInstance(
              getLabelAngle() + Math.PI / 2.0, labelBounds.getCenterX(), labelBounds.getCenterY());
      Shape rotatedLabelBounds = t.createTransformedShape(labelBounds);
      labelBounds = rotatedLabelBounds.getBounds2D();
      double labelx = state.getCursor() + insets.getLeft() + labelBounds.getWidth() / 2.0;
      double labely = dataArea.getY() + dataArea.getHeight() / 2.0;
      TextUtilities.drawRotatedString(
          label,
          g2,
          (float) labelx,
          (float) labely,
          TextAnchor.CENTER,
          getLabelAngle() + Math.PI / 2.0,
          TextAnchor.CENTER);
      state.cursorRight(insets.getLeft() + labelBounds.getWidth() + insets.getRight());
    }

    return state;
  }
Exemple #3
0
  /**
   * Draws the category labels and returns the updated axis state.
   *
   * @param g2 the graphics device (<code>null</code> not permitted).
   * @param plotArea the plot area (<code>null</code> not permitted).
   * @param dataArea the area inside the axes (<code>null</code> not permitted).
   * @param edge the axis location (<code>null</code> not permitted).
   * @param state the axis state (<code>null</code> not permitted).
   * @param plotState collects information about the plot (<code>null</code> permitted).
   * @return The updated axis state (never <code>null</code>).
   */
  protected AxisState drawSubCategoryLabels(
      Graphics2D g2,
      Rectangle2D plotArea,
      Rectangle2D dataArea,
      RectangleEdge edge,
      AxisState state,
      PlotRenderingInfo plotState) {

    if (state == null) {
      throw new IllegalArgumentException("Null 'state' argument.");
    }

    g2.setFont(this.subLabelFont);
    g2.setPaint(this.subLabelPaint);
    CategoryPlot plot = (CategoryPlot) getPlot();
    CategoryDataset dataset = plot.getDataset();
    int categoryCount = dataset.getColumnCount();

    double maxdim = getMaxDim(g2, edge);
    for (int categoryIndex = 0; categoryIndex < categoryCount; categoryIndex++) {

      double x0 = 0.0;
      double x1 = 0.0;
      double y0 = 0.0;
      double y1 = 0.0;
      if (edge == RectangleEdge.TOP) {
        x0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge);
        x1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge);
        y1 = state.getCursor();
        y0 = y1 - maxdim;
      } else if (edge == RectangleEdge.BOTTOM) {
        x0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge);
        x1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge);
        y0 = state.getCursor();
        y1 = y0 + maxdim;
      } else if (edge == RectangleEdge.LEFT) {
        y0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge);
        y1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge);
        x1 = state.getCursor();
        x0 = x1 - maxdim;
      } else if (edge == RectangleEdge.RIGHT) {
        y0 = getCategoryStart(categoryIndex, categoryCount, dataArea, edge);
        y1 = getCategoryEnd(categoryIndex, categoryCount, dataArea, edge);
        x0 = state.getCursor();
        x1 = x0 + maxdim;
      }
      Rectangle2D area = new Rectangle2D.Double(x0, y0, (x1 - x0), (y1 - y0));
      int subCategoryCount = this.subCategories.size();
      float width = (float) ((x1 - x0) / subCategoryCount);
      float height = (float) ((y1 - y0) / subCategoryCount);
      float xx = 0.0f;
      float yy = 0.0f;
      for (int i = 0; i < subCategoryCount; i++) {
        if (RectangleEdge.isTopOrBottom(edge)) {
          xx = (float) (x0 + (i + 0.5) * width);
          yy = (float) area.getCenterY();
        } else {
          xx = (float) area.getCenterX();
          yy = (float) (y0 + (i + 0.5) * height);
        }
        String label = this.subCategories.get(i).toString();
        TextUtilities.drawRotatedString(
            label, g2, xx, yy, TextAnchor.CENTER, 0.0, TextAnchor.CENTER);
      }
    }

    if (edge.equals(RectangleEdge.TOP)) {
      double h = maxdim;
      state.cursorUp(h);
    } else if (edge.equals(RectangleEdge.BOTTOM)) {
      double h = maxdim;
      state.cursorDown(h);
    } else if (edge == RectangleEdge.LEFT) {
      double w = maxdim;
      state.cursorLeft(w);
    } else if (edge == RectangleEdge.RIGHT) {
      double w = maxdim;
      state.cursorRight(w);
    }
    return state;
  }
 /**
  * Draws the major and minor tick marks for an axis that lies at the top or bottom of the plot.
  *
  * @param g2 the graphics device.
  * @param state the axis state.
  * @param dataArea the data area.
  * @param edge the edge.
  */
 protected void drawTickMarksHorizontal(
     Graphics2D g2, AxisState state, Rectangle2D dataArea, RectangleEdge edge) {
   List<ValueTick> ticks = new ArrayList<ValueTick>();
   double x0;
   double y0 = state.getCursor();
   double insideLength = getTickMarkInsideLength();
   double outsideLength = getTickMarkOutsideLength();
   RegularTimePeriod t =
       createInstance(
           this.majorTickTimePeriodClass, this.first.getStart(), getTimeZone(), this.locale);
   long t0 = t.getFirstMillisecond();
   Line2D inside = null;
   Line2D outside = null;
   long firstOnAxis = getFirst().getFirstMillisecond();
   long lastOnAxis = getLast().getLastMillisecond() + 1;
   while (t0 <= lastOnAxis) {
     ticks.add(new NumberTick((double) t0, "", TextAnchor.CENTER, TextAnchor.CENTER, 0.0));
     x0 = valueToJava2D(t0, dataArea, edge);
     if (edge == RectangleEdge.TOP) {
       inside = new Line2D.Double(x0, y0, x0, y0 + insideLength);
       outside = new Line2D.Double(x0, y0, x0, y0 - outsideLength);
     } else if (edge == RectangleEdge.BOTTOM) {
       inside = new Line2D.Double(x0, y0, x0, y0 - insideLength);
       outside = new Line2D.Double(x0, y0, x0, y0 + outsideLength);
     }
     if (t0 >= firstOnAxis) {
       g2.setPaint(getTickMarkPaint());
       g2.setStroke(getTickMarkStroke());
       g2.draw(inside);
       g2.draw(outside);
     }
     // draw minor tick marks
     if (this.minorTickMarksVisible) {
       RegularTimePeriod tminor =
           createInstance(this.minorTickTimePeriodClass, new Date(t0), getTimeZone(), this.locale);
       long tt0 = tminor.getFirstMillisecond();
       while (tt0 < t.getLastMillisecond() && tt0 < lastOnAxis) {
         double xx0 = valueToJava2D(tt0, dataArea, edge);
         if (edge == RectangleEdge.TOP) {
           inside = new Line2D.Double(xx0, y0, xx0, y0 + this.minorTickMarkInsideLength);
           outside = new Line2D.Double(xx0, y0, xx0, y0 - this.minorTickMarkOutsideLength);
         } else if (edge == RectangleEdge.BOTTOM) {
           inside = new Line2D.Double(xx0, y0, xx0, y0 - this.minorTickMarkInsideLength);
           outside = new Line2D.Double(xx0, y0, xx0, y0 + this.minorTickMarkOutsideLength);
         }
         if (tt0 >= firstOnAxis) {
           g2.setPaint(this.minorTickMarkPaint);
           g2.setStroke(this.minorTickMarkStroke);
           g2.draw(inside);
           g2.draw(outside);
         }
         tminor = tminor.next();
         tminor.peg(this.calendar);
         tt0 = tminor.getFirstMillisecond();
       }
     }
     t = t.next();
     t.peg(this.calendar);
     t0 = t.getFirstMillisecond();
   }
   if (edge == RectangleEdge.TOP) {
     state.cursorUp(Math.max(outsideLength, this.minorTickMarkOutsideLength));
   } else if (edge == RectangleEdge.BOTTOM) {
     state.cursorDown(Math.max(outsideLength, this.minorTickMarkOutsideLength));
   }
   state.setTicks(ticks);
 }
  /**
   * Draws the category labels and returns the updated axis state.
   *
   * @param g2 the graphics device (<code>null</code> not permitted).
   * @param plotArea the plot area (<code>null</code> not permitted).
   * @param dataArea the area inside the axes (<code>null</code> not permitted).
   * @param edge the axis location (<code>null</code> not permitted).
   * @param state the axis state (<code>null</code> not permitted).
   * @param plotState collects information about the plot (<code>null</code> permitted).
   * @return The updated axis state (never <code>null</code>).
   */
  protected AxisState drawCategoryLabels(
      Graphics2D g2,
      Rectangle2D plotArea,
      Rectangle2D dataArea,
      RectangleEdge edge,
      AxisState state,
      PlotRenderingInfo plotState) {

    ParamChecks.nullNotPermitted(state, "state");
    if (!isTickLabelsVisible()) {
      return state;
    }
    List<CategoryTick> ticks = refreshTicks(g2, state, plotArea, edge);
    // state.setTicks(ticks);        //FIXME MMC had to remove this as the types don't match

    int categoryIndex = 0;
    for (CategoryTick tick : ticks) {

      g2.setFont(getTickLabelFont(tick.getCategory()));
      g2.setPaint(getTickLabelPaint(tick.getCategory()));

      CategoryLabelPosition position = this.categoryLabelPositions.getLabelPosition(edge);
      double x0 = 0.0;
      double x1 = 0.0;
      double y0 = 0.0;
      double y1 = 0.0;
      if (edge == RectangleEdge.TOP) {
        x0 = getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
        x1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
        y1 = state.getCursor() - this.categoryLabelPositionOffset;
        y0 = y1 - state.getMax();
      } else if (edge == RectangleEdge.BOTTOM) {
        x0 = getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
        x1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
        y0 = state.getCursor() + this.categoryLabelPositionOffset;
        y1 = y0 + state.getMax();
      } else if (edge == RectangleEdge.LEFT) {
        y0 = getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
        y1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
        x1 = state.getCursor() - this.categoryLabelPositionOffset;
        x0 = x1 - state.getMax();
      } else if (edge == RectangleEdge.RIGHT) {
        y0 = getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
        y1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea, edge);
        x0 = state.getCursor() + this.categoryLabelPositionOffset;
        x1 = x0 - state.getMax();
      }
      Rectangle2D area = new Rectangle2D.Double(x0, y0, (x1 - x0), (y1 - y0));
      Point2D anchorPoint = RectangleAnchor.coordinates(area, position.getCategoryAnchor());
      TextBlock block = tick.getLabel();
      block.draw(
          g2,
          (float) anchorPoint.getX(),
          (float) anchorPoint.getY(),
          position.getLabelAnchor(),
          (float) anchorPoint.getX(),
          (float) anchorPoint.getY(),
          position.getAngle());
      Shape bounds =
          block.calculateBounds(
              g2,
              (float) anchorPoint.getX(),
              (float) anchorPoint.getY(),
              position.getLabelAnchor(),
              (float) anchorPoint.getX(),
              (float) anchorPoint.getY(),
              position.getAngle());
      if (plotState != null && plotState.getOwner() != null) {
        EntityCollection entities = plotState.getOwner().getEntityCollection();
        if (entities != null) {
          String tooltip = getCategoryLabelToolTip(tick.getCategory());
          String url = getCategoryLabelURL(tick.getCategory());
          entities.add(new CategoryLabelEntity(tick.getCategory(), bounds, tooltip, url));
        }
      }
      categoryIndex++;
    }

    if (edge.equals(RectangleEdge.TOP)) {
      double h = state.getMax() + this.categoryLabelPositionOffset;
      state.cursorUp(h);
    } else if (edge.equals(RectangleEdge.BOTTOM)) {
      double h = state.getMax() + this.categoryLabelPositionOffset;
      state.cursorDown(h);
    } else if (edge == RectangleEdge.LEFT) {
      double w = state.getMax() + this.categoryLabelPositionOffset;
      state.cursorLeft(w);
    } else if (edge == RectangleEdge.RIGHT) {
      double w = state.getMax() + this.categoryLabelPositionOffset;
      state.cursorRight(w);
    }
    return state;
  }