this.areas = new BarGraphArea[this.count];
double max = kind == TIME_LOG ? Math.log(this.maxValue) : this.maxValue;
for (int i=0, y=MARGIN; i < this.count; i++, y+=LINE_HEIGHT) {
// get builds info
ConfigResults configResults = this.results[i];
this.areas[i] = new BarGraphArea(configResults);
BarGraphArea graphArea = this.areas[i];
BuildResults currentBuildResults = configResults.getCurrentBuildResults();
double currentValue = currentBuildResults.getValue();
double currentError = currentBuildResults.getError();
double error = configResults.getError();
boolean singleTest = Double.isNaN(error);
boolean isSignificant = singleTest || error < Utils.STANDARD_ERROR_THRESHOLD;
boolean isCommented = currentBuildResults.getComment() != null;
BuildResults baselineBuildResults = configResults.getBaselineBuildResults();
double baselineValue = baselineBuildResults.getValue();
double baselineError = baselineBuildResults.getError();
// draw baseline build bar
Color whiteref = (Color) this.resources.get("whiteref");
if (whiteref == null) {
whiteref = new Color(DEFAULT_DISPLAY, 240, 240, 248);
this.resources.put("whiteref", whiteref);
}
this.gc.setBackground(whiteref);
double baselineGraphValue = kind == TIME_LOG ? Math.log(baselineValue) : baselineValue;
int baselineBarLength= (int) (baselineGraphValue / max * this.graphWidth);
int baselineErrorLength= (int) (baselineError / max * this.graphWidth / 2);
int labelxpos = MARGIN + baselineBarLength;
if (kind == TIME_LOG || baselineErrorLength <= 1) {
this.gc.fillRectangle(MARGIN, y + (GAP/2), baselineBarLength, BAR_HEIGHT);
Rectangle rec = new Rectangle(MARGIN, y + (GAP/2), baselineBarLength, BAR_HEIGHT);
this.gc.drawRectangle(rec);
graphArea.addArea(rec, "Time for baseline build "+baselineBuildResults.getName()+": "+Util.timeString((long)baselineValue));
} else {
int wr = baselineBarLength - baselineErrorLength;
Rectangle recValue = new Rectangle(MARGIN, y + (GAP/2), wr, BAR_HEIGHT);
this.gc.fillRectangle(recValue);
this.gc.setBackground(YELLOW);
Rectangle recError = new Rectangle(MARGIN+wr, y + (GAP/2), baselineErrorLength*2, BAR_HEIGHT);
this.gc.fillRectangle(recError);
Rectangle rec = new Rectangle(MARGIN, y + (GAP/2), baselineBarLength+baselineErrorLength, BAR_HEIGHT);
this.gc.drawRectangle(rec);
StringBuffer tooltip = new StringBuffer("Time for baseline build ");
tooltip.append(baselineBuildResults.getName());
tooltip.append(": ");
tooltip.append(Util.timeString((long)baselineValue));
tooltip.append(" [±");
tooltip.append(Util.timeString((long)baselineError));
tooltip.append(']');
graphArea.addArea(rec, tooltip.toString());
labelxpos += baselineErrorLength;
}
// set current build bar color
if (baselineValue < currentValue) {
if (isCommented) {
this.gc.setBackground(GRAY);
} else {
this.gc.setBackground(failureColor);
}
} else {
this.gc.setBackground(okColor);
}
// draw current build bar
double currentGraphValue = kind == TIME_LOG ? Math.log(currentValue) : currentValue;
int currentBarLength= (int) (currentGraphValue / max * this.graphWidth);
int currentErrorLength= (int) (currentError / max * this.graphWidth / 2);
if (kind == TIME_LOG || currentErrorLength <= 1) {
this.gc.fillRectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, currentBarLength, BAR_HEIGHT);
Rectangle rec = new Rectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, currentBarLength, BAR_HEIGHT);
this.gc.drawRectangle(rec);
String tooltip = "Time for current build "+currentBuildResults.getName()+": "+Util.timeString((long)currentValue);
if (isCommented) {
tooltip += ". " + currentBuildResults.getComment();
}
graphArea.addArea(rec, tooltip);
if (labelxpos < (MARGIN+currentBarLength)) {
labelxpos = MARGIN + currentBarLength;
}
} else {
int wr = currentBarLength - currentErrorLength;
Rectangle recValue = new Rectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, wr, BAR_HEIGHT);
this.gc.fillRectangle(recValue);
this.gc.setBackground(YELLOW);
Rectangle recError = new Rectangle(MARGIN+wr, y + (GAP/2) + BAR_HEIGHT, currentErrorLength*2, BAR_HEIGHT);
this.gc.fillRectangle(recError);
Rectangle rec = new Rectangle(MARGIN, y + (GAP/2) + BAR_HEIGHT, currentBarLength+currentErrorLength, BAR_HEIGHT);
this.gc.drawRectangle(rec);
StringBuffer tooltip = new StringBuffer("Time for current build ");
tooltip.append(currentBuildResults.getName());
tooltip.append(": ");
tooltip.append(Util.timeString((long)currentValue));
tooltip.append(" [±");
tooltip.append(Util.timeString((long)currentError));
tooltip.append(']');
if (isCommented) {
tooltip.append(". ");
tooltip.append(currentBuildResults.getComment());
}
graphArea.addArea(rec, tooltip.toString());
if (labelxpos < (MARGIN+currentBarLength+currentErrorLength)) {
labelxpos = MARGIN + currentBarLength+currentErrorLength;
}
}
// set delta value style and color
boolean hasFailure = currentBuildResults.getFailure() != null;
if (hasFailure) {
if (isCommented) {
this.gc.setForeground(DARK_GRAY);
} else {
this.gc.setForeground(RED);
}
} else {
this.gc.setForeground(BLACK);
}
// draw delta value
double delta = -configResults.getDelta();
String label = delta > 0 ? "+" : "";
label += NUMBER_FORMAT.format(delta*100) + "%";
Point labelExtent= this.gc.stringExtent(label);
int labelvpos= y + (LINE_HEIGHT - labelExtent.y) / 2;
this.gc.drawString(label, labelxpos+TGAP, labelvpos, true);
this.gc.setForeground(BLACK);
this.gc.setFont(null);
int titleStart = (int) (RATIO * this.imageWidth);
if (singleTest || !isSignificant) {
String deltaTooltip = null;
if (singleTest) {
deltaTooltip = "This test performed only one iteration; hence its reliability cannot be assessed";
} else if (!isSignificant) {
deltaTooltip = "This test has a bad reliability: error is "+NUMBER_FORMAT.format(error*100)+"% (> 3%)!";
}
Image warning = (Image) this.resources.get("warning");
int xi = labelxpos+TGAP+labelExtent.x;
this.gc.drawImage(warning, xi, labelvpos);
ImageData imageData = warning.getImageData();
// Set zones
// - first one is between end of bar and warning image beginning
Rectangle deltaZone = new Rectangle(labelxpos, labelvpos-2, xi-labelxpos, labelExtent.y+4);
graphArea.addArea(deltaZone, null);
// - second one is the warning image
Rectangle warningZone = new Rectangle(xi, labelvpos, imageData.width, imageData.height);
graphArea.addArea(warningZone, deltaTooltip);
// - last one is between end of the warning image and the scenario title beginning
int warningImageEnd = xi+imageData.width;
Rectangle emptyZone = new Rectangle(warningImageEnd, labelvpos, titleStart-warningImageEnd, imageData.height);
graphArea.addArea(emptyZone, deltaTooltip);
} else {
// No tooltip => delta zone is between end of bar and the scenario title beginning
Rectangle deltaZone = new Rectangle(labelxpos, labelvpos-2, titleStart-labelxpos, labelExtent.y+4);
graphArea.addArea(deltaZone, null);
}
// set title style
Color oldfg= this.gc.getForeground();
this.gc.setForeground(BLUE);
// draw scenario title
int x= titleStart;
ScenarioResults scenarioResults = (ScenarioResults) configResults.getParent();
String title = scenarioResults.getLabel() + " (" + this.defaultDimName + ")";
Point e= this.gc.stringExtent(title);
this.gc.drawLine(x, labelvpos + e.y - 1, x + e.x, labelvpos + e.y - 1);
this.gc.drawString(title, x, labelvpos, true);
this.gc.setForeground(oldfg);
this.gc.setFont(null);
Rectangle titleZone = new Rectangle(x, labelvpos, e.x, e.y);
graphArea.addArea(titleZone, null/*no tooltip*/);
if (!configResults.isBaselined()) {
Image warning = (Image) this.resources.get("warning");
this.gc.drawImage(warning, x+e.x, labelvpos);
ImageData imageData = warning.getImageData();
Rectangle warningZone = new Rectangle(x+e.x, labelvpos, imageData.width, imageData.height);
String titleTooltip = "This test has no baseline result, hence use build "+configResults.getBaselineBuildName()+" for reference!";
graphArea.addArea(warningZone, titleTooltip);
}
}
}