added clickable map.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@1563 71c3de6d-444a-0410-be80-ed276b4c234a
This commit is contained in:
kohsuke committed 2006-12-30 21:11:54 +00:00
1 parent 0d4b6136dd
commit a61d87fb85
3 files changed
+171 -6

No files matched your search

+149 -5
View File
@@ -21,19 +21,27 @@ 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.AreaRenderer;
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;
@@ -530,6 +538,14 @@ public abstract class Job<JobT extends Job<JobT,RunT>, RunT extends Run<JobT,Run
* Returns the graph that shows how long each build took.
*/
public void doBuildTimeGraph( StaplerRequest req, StaplerResponse rsp ) throws IOException {
ChartUtil.generateGraph(req,rsp, createBuildTimeTrendChart(),500,400);
}
public void doBuildTimeGraphMap( StaplerRequest req, StaplerResponse rsp ) throws IOException {
ChartUtil.generateClickableMap(req,rsp, createBuildTimeTrendChart(),500,400);
}
private JFreeChart createBuildTimeTrendChart() {
class Label implements Comparable<Label> {
private final Run run;
@@ -567,6 +583,10 @@ public abstract class Job<JobT extends Job<JobT,RunT>, RunT extends Run<JobT,Run
}
return l;
}
public String getURL() {
return String.valueOf(run.number);
}
}
DataSetBuilder<String,Label> data = new DataSetBuilder<String, Label>();
@@ -609,20 +629,144 @@ public abstract class Job<JobT extends Job<JobT,RunT>, RunT extends Run<JobT,Run
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
plot.setRenderer(new StackedAreaRenderer() {
StackedAreaRenderer ar = new StackedAreaRenderer() {
public Paint getItemPaint(int row, int column) {
Label key = (Label) dataset.getColumnKey(column);
return key.getColor();
}
});
AreaRenderer ar = (AreaRenderer) plot.getRenderer();
// 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));
}
}
}
}
}
};
ar.setEndType(AreaRendererEndType.TRUNCATE);
ar.setSeriesPaint(0,ColorPalette.BLUE);
ar.setItemURLGenerator(new CategoryURLGenerator() {
public String generateURL(CategoryDataset dataset, int row, int column) {
Label label = (Label) dataset.getColumnKey(column);
return label.getURL();
}
});
ar.setToolTipGenerator(new CategoryToolTipGenerator() {
public String generateToolTip(CategoryDataset dataset, int row, int column) {
Label label = (Label) dataset.getColumnKey(column);
return label.toString();
}
});
plot.setRenderer(ar);
// crop extra space around the graph
plot.setInsets(new RectangleInsets(0,0,0,5.0));
ChartUtil.generateGraph(req,rsp,chart,500,400);
return chart;
}
/**
@@ -1,6 +1,8 @@
package hudson.util;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
@@ -52,6 +54,9 @@ public class ChartUtil {
*/
public static boolean awtProblem = false;
/**
* Generates the graph in PNG format and sends that to the response.
*/
public static void generateGraph(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, int defaultW, int defaultH) throws IOException {
try {
String w = req.getParameter("width");
@@ -69,6 +74,22 @@ public class ChartUtil {
}
}
/**
* Generates the clickable map info and sends that to the response.
*/
public static void generateClickableMap(StaplerRequest req, StaplerResponse rsp, JFreeChart chart, int defaultW, int defaultH) throws IOException {
String w = req.getParameter("width");
if(w==null) w=String.valueOf(defaultW);
String h = req.getParameter("height");
if(h==null) h=String.valueOf(defaultH);
ChartRenderingInfo info = new ChartRenderingInfo();
chart.createBufferedImage(Integer.parseInt(w),Integer.parseInt(h),info);
rsp.setContentType("text/html;charset=UTF-8");
rsp.getWriter().println(ChartUtilities.getImageMap( "map", info ));
}
static {
try {
new Font("SansSerif",Font.BOLD,18).toString();
@@ -4,7 +4,7 @@
<st:include page="sidepanel.jelly" />
<l:main-panel>
<div align="center">
<img src="buildTimeGraph" width="500" height="400"/>
<img src="buildTimeGraph" width="500" height="400" lazymap="buildTimeGraphMap"/>
</div>
<j:set var="isMasterSlaveEnabled" value="${!empty(app.slaves)}"/>