diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index 2badd4d52c43e535516c98e1af10428efd464a30..74369a2b5475d070d76a2c1a80e04de3be19d486 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -12,6 +12,7 @@ import hudson.util.DataSetBuilder; import hudson.util.IOException2; import hudson.util.RunList; import hudson.util.ShiftedCategoryAxis; +import hudson.util.StackedAreaRenderer2; import hudson.util.TextFile; import hudson.util.XStream2; import org.apache.tools.ant.taskdefs.Copy; @@ -21,27 +22,17 @@ import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.CategoryLabelPositions; import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.entity.EntityCollection; -import org.jfree.chart.labels.CategoryToolTipGenerator; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.AreaRendererEndType; -import org.jfree.chart.renderer.category.CategoryItemRendererState; import org.jfree.chart.renderer.category.StackedAreaRenderer; -import org.jfree.chart.urls.CategoryURLGenerator; import org.jfree.data.category.CategoryDataset; -import org.jfree.ui.RectangleEdge; import org.jfree.ui.RectangleInsets; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import javax.servlet.ServletException; import java.awt.Color; -import java.awt.Graphics2D; import java.awt.Paint; -import java.awt.Polygon; -import java.awt.geom.Rectangle2D; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -547,7 +538,7 @@ public abstract class Job, RunT extends Run { - private final Run run; + final Run run; public Label(Run r) { this.run = r; @@ -584,13 +575,6 @@ public abstract class Job, RunT extends Run data = new DataSetBuilder(); @@ -633,138 +617,25 @@ public abstract class Job, RunT extends Run + *
  • Built-in support for {@link #generateToolTip(CategoryDataset, int, int) tooltip} + * and {@link #generateURL(CategoryDataset, int, int) hyperlinks} for clickable map. + *
  • Clickable map hit test is modified so that the entire area is clickable, + * not just the small area around each data point. + *
  • Rendering algorithm is modified so that + * {@link #getItemPaint(int, int) different color on the same data series} + * will look more natural. + * + * + * @author Kohsuke Kawaguchi +*/ +public class StackedAreaRenderer2 extends StackedAreaRenderer + implements CategoryToolTipGenerator, CategoryURLGenerator { + + public StackedAreaRenderer2() { + setEndType(AreaRendererEndType.TRUNCATE); + setItemURLGenerator(this); + setToolTipGenerator(this); + } + + /** + * Override this method to specify the hyperlink target of the given data point. + */ + public String generateURL(CategoryDataset dataset, int row, int column) { + return null; + } + + /** + * Override this method to specify the tool tip text of the given data point. + */ + public String generateToolTip(CategoryDataset dataset, int row, int column) { + return null; + } + + /** + * Override this method to specify the color to draw the given area. + */ + public Paint getItemPaint(int row, int column) { + return super.getItemPaint(row, column); + } + + // Mostly copied from the base class. + @Override + public void drawItem(Graphics2D g2, + CategoryItemRendererState state, + Rectangle2D dataArea, + CategoryPlot plot, + CategoryAxis domainAxis, + ValueAxis rangeAxis, + CategoryDataset dataset, + int row, + int column, + int pass) { + + // plot non-null values... + Number dataValue = dataset.getValue(row, column); + if (dataValue == null) { + return; + } + + double value = dataValue.doubleValue(); + + // leave the y values (y1, y0) untranslated as it is going to be be + // stacked up later by previous series values, after this it will be + // translated. + double xx1 = domainAxis.getCategoryMiddle(column, getColumnCount(), + dataArea, plot.getDomainAxisEdge()); + + double previousHeightx1 = getPreviousHeight(dataset, row, column); + double y1 = value + previousHeightx1; + RectangleEdge location = plot.getRangeAxisEdge(); + double yy1 = rangeAxis.valueToJava2D(y1, dataArea, location); + + g2.setPaint(getItemPaint(row, column)); + g2.setStroke(getItemStroke(row, column)); + + // add an item entity, if this information is being collected + EntityCollection entities = state.getEntityCollection(); + + // in column zero, the only job to do is draw any visible item labels + // and this is done in the second pass... + if (column == 0) { + if (pass == 1) { + // draw item labels, if visible + if (isItemLabelVisible(row, column)) { + drawItemLabel(g2, plot.getOrientation(), dataset, row, column, + xx1, yy1, (y1 < 0.0)); + } + } + } else { + Number previousValue = dataset.getValue(row, column - 1); + if (previousValue != null) { + + double xx0 = domainAxis.getCategoryMiddle(column - 1, + getColumnCount(), dataArea, plot.getDomainAxisEdge()); + double y0 = previousValue.doubleValue(); + + + // Get the previous height, but this will be different for both + // y0 and y1 as the previous series values could differ. + double previousHeightx0 = getPreviousHeight(dataset, row, + column - 1); + + // Now stack the current y values on top of the previous values. + y0 += previousHeightx0; + + // Now translate the previous heights + double previousHeightxx0 = rangeAxis.valueToJava2D( + previousHeightx0, dataArea, location); + double previousHeightxx1 = rangeAxis.valueToJava2D( + previousHeightx1, dataArea, location); + + // Now translate the current y values. + double yy0 = rangeAxis.valueToJava2D(y0, dataArea, location); + + if (pass == 0) { + // left half + Polygon p = new Polygon(); + p.addPoint((int) xx0, (int) yy0); + p.addPoint((int) (xx0+xx1)/2, (int) (yy0+yy1)/2); + p.addPoint((int) (xx0+xx1)/2, (int) (previousHeightxx0+previousHeightxx1)/2); + p.addPoint((int) xx0, (int) previousHeightxx0); + + g2.setPaint(getItemPaint(row, column-1)); + g2.setStroke(getItemStroke(row, column-1)); + g2.fill(p); + + if (entities != null) + addItemEntity(entities, dataset, row, column-1, p); + + // right half + p = new Polygon(); + p.addPoint((int) xx1, (int) yy1); + p.addPoint((int) (xx0+xx1)/2, (int) (yy0+yy1)/2); + p.addPoint((int) (xx0+xx1)/2, (int) (previousHeightxx0+previousHeightxx1)/2); + p.addPoint((int) xx1, (int) previousHeightxx1); + + g2.setPaint(getItemPaint(row, column)); + g2.setStroke(getItemStroke(row, column)); + g2.fill(p); + + if (entities != null) + addItemEntity(entities, dataset, row, column, p); + } else { + if (isItemLabelVisible(row, column)) { + drawItemLabel(g2, plot.getOrientation(), dataset, row, + column, xx1, yy1, (y1 < 0.0)); + } + } + } + } + } +}