mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-11 19:16:42 +00:00
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:
1 parent
0d4b6136dd
commit
a61d87fb85
3 files changed
+171
-6
No files matched your search
@@ -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)}"/>
|
||||
|
||||
Reference in new issue
Block a user