use of org.apache.pivot.wtk.Gauge in project pivot by apache.
the class TerraGaugeSkin method paint.
@Override
public void paint(Graphics2D graphics) {
@SuppressWarnings("unchecked") Gauge<T> gauge = (Gauge<T>) getComponent();
// NOTE: sanity check: warning level > min && < max, warning < critical if both set
// also critical > main && < max, critical > warning if both set
String text = gauge.getText();
T value = gauge.getValue();
T minLevel = gauge.getMinValue();
T maxLevel = gauge.getMaxValue();
T warningLevel = gauge.getWarningLevel();
T criticalLevel = gauge.getCriticalLevel();
Dimensions size = gauge.getSize();
Origin origin = gauge.getOrigin();
// The pen thickness is centered on the path, so we need to calculate the path diameter for the
// center of the stroke width (basically 1/2 the thickness on each side, or the thickness itself)
// And only account for the border thickness (the outer part) if > 1.0
boolean showingBorder = showBorder && borderColor != null;
float borderAdjust = (showingBorder ? (borderThickness > 1.0f ? borderThickness : 0.0f) : 0.0f);
float diameter = (float) (Math.min(size.width - padding.getWidth(), size.height - padding.getHeight())) - thickness - (borderAdjust * 2.0f);
float x = ((float) size.width - diameter) / 2.0f;
float y = ((float) size.height - diameter) / 2.0f;
Rectangle2D rect = new Rectangle2D.Float(x, y, diameter, diameter);
float minValue = minLevel == null ? 0.0f : minLevel.floatValue();
float maxValue = maxLevel == null ? 100.0f : maxLevel.floatValue();
float fullRange = maxValue - minValue;
float toAngle = 360.0f / fullRange;
float activeValue = (value == null ? 0.0f : value.floatValue()) - minValue;
float activeAngle = activeValue * toAngle;
if (backgroundColor != null) {
graphics.setColor(backgroundColor);
graphics.fillRect(0, 0, size.width, size.height);
}
graphics.setRenderingHints(renderingHints);
graphics.setStroke(new BasicStroke(thickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
// Note: presume that critical > warning if both are set
Color maxColor = null;
if (warningLevel != null && warningColor != null) {
float warningValue = warningLevel.floatValue() - minValue;
if (activeValue >= warningValue) {
float warningAngle = warningValue * toAngle;
if (criticalLevel != null && criticalColor != null) {
float criticalValue = criticalLevel.floatValue() - minValue;
if (activeValue >= criticalValue) {
if (onlyMaxColor) {
maxColor = criticalColor;
} else {
// Three segments here: min->warning (normal color), warning->critical (warning color), critical->active (critical color)
float criticalAngle = criticalValue * toAngle;
drawArc(graphics, rect, origin, 0.0f, warningAngle, color);
drawArc(graphics, rect, origin, warningAngle, criticalAngle - warningAngle, warningColor);
drawArc(graphics, rect, origin, criticalAngle, activeAngle - criticalAngle, criticalColor);
}
} else {
if (onlyMaxColor) {
maxColor = warningColor;
} else {
// Two segments here: min->warning (normal), warning->active (warning)
drawArc(graphics, rect, origin, 0.0f, warningAngle, color);
drawArc(graphics, rect, origin, warningAngle, activeAngle - warningAngle, warningColor);
}
}
} else {
if (onlyMaxColor) {
maxColor = warningColor;
} else {
// Two segments here: min->warning (normal), warning->active (warning color)
drawArc(graphics, rect, origin, 0.0f, warningAngle, color);
drawArc(graphics, rect, origin, warningAngle, activeAngle - warningAngle, warningColor);
}
}
} else {
// Just one segment, the normal value
drawArc(graphics, rect, origin, 0.0f, activeAngle, color);
}
} else if (criticalLevel != null && criticalColor != null) {
float criticalValue = criticalLevel.floatValue() - minValue;
if (activeValue > criticalValue) {
if (onlyMaxColor) {
maxColor = criticalColor;
} else {
// Two here: min->critical (normal color), critical->active (critical color)
float criticalAngle = criticalValue * toAngle;
drawArc(graphics, rect, origin, 0.0f, criticalAngle, color);
drawArc(graphics, rect, origin, criticalAngle, activeAngle - criticalAngle, criticalColor);
}
} else {
// One, min->active (normal color)
drawArc(graphics, rect, origin, 0.0f, activeAngle, color);
}
} else {
// Else just one segment (min->active, normal color)
drawArc(graphics, rect, origin, 0.0f, activeAngle, color);
}
// Now if we didn't draw the multiple segments because of "onlyMaxColor" do it now
if (onlyMaxColor && maxColor != null) {
drawArc(graphics, rect, origin, 0.0f, activeAngle, maxColor);
}
// Now draw the "inactive" part the rest of the way
if (activeAngle < 360.0f) {
drawArc(graphics, rect, origin, activeAngle, 360.0f - activeAngle, gaugeColor);
}
// Now draw the border strokes if requested around the whole circle
if (showingBorder) {
graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
graphics.setStroke(new BasicStroke(borderThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
float border = borderThickness > 1.0f ? borderThickness : 0.0f;
float halfStroke = (thickness + border) / 2.0f;
float thicknessAdjust = thickness + border;
Rectangle2D rectOuter = new Rectangle2D.Float(x - halfStroke, y - halfStroke, diameter + thicknessAdjust, diameter + thicknessAdjust);
Rectangle2D rectInner = new Rectangle2D.Float(x + halfStroke, y + halfStroke, diameter - thicknessAdjust, diameter - thicknessAdjust);
drawArc(graphics, rectInner, origin, 360.0f, 360.0f, borderColor);
drawArc(graphics, rectOuter, origin, 360.0f, 360.0f, borderColor);
}
// On top of the arcs, draw the tick marks (if requested)
if (showTickMarks && tickFrequency != null && tickColor != null) {
// frequency is how many gauge values between marks
float frequency = tickFrequency.floatValue();
int numMarks = (int) Math.floor(fullRange / frequency);
graphics.setColor(tickColor == null ? backgroundColor : tickColor);
// Note: VALUE_STROKE_PURE tends to make the arcs fine but the lines non-uniform,
// while VALUE_STROKE_NORMALIZE works well for the lines but makes the arcs "wobble" around a bit
graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
graphics.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
float radius = diameter / 2.0f;
float innerRadius = radius - (thickness / 2.0f);
float outerRadius = radius + (thickness / 2.0f);
float xCenter = x + radius;
float yCenter = y + radius;
// Draw the "0" mark at the origin
switch(origin) {
case NORTH:
graphics.drawLine((int) xCenter, (int) (yCenter - innerRadius), (int) xCenter, (int) (yCenter - outerRadius));
break;
case EAST:
graphics.drawLine((int) (xCenter + innerRadius), (int) yCenter, (int) (xCenter + outerRadius), (int) yCenter);
break;
case SOUTH:
graphics.drawLine((int) xCenter, (int) (yCenter + innerRadius), (int) xCenter, (int) (yCenter + outerRadius));
break;
case WEST:
graphics.drawLine((int) (xCenter - innerRadius), (int) yCenter, (int) (xCenter - outerRadius), (int) yCenter);
break;
}
// Draw clockwise from the origin, subtracting the frequency each time
double startAngleRadians = origin.getOriginAngle() * Math.PI / 180.0;
double frequencyAngleRadians = frequency / fullRange * Math.PI * 2.0;
double angleRadians = startAngleRadians - frequencyAngleRadians;
for (int i = 0; i < numMarks; i++) {
float cosAngle = (float) Math.cos(angleRadians);
float sinAngle = (float) Math.sin(angleRadians);
int xInner = (int) (xCenter + (innerRadius * cosAngle) + 0.5f);
int yInner = (int) (yCenter + (innerRadius * sinAngle) + 0.5f);
int xOuter = (int) (xCenter + (outerRadius * cosAngle) + 0.5f);
int yOuter = (int) (yCenter + (outerRadius * sinAngle) + 0.5f);
graphics.drawLine(xInner, yInner, xOuter, yOuter);
angleRadians -= frequencyAngleRadians;
}
}
// Draw the text in the middle (if any)
if (!Utils.isNullOrEmpty(text)) {
FontRenderContext fontRenderContext = GraphicsUtilities.prepareForText(graphics, font, textColor);
LineMetrics lm = font.getLineMetrics(text, fontRenderContext);
Rectangle2D textBounds = font.getStringBounds(text, fontRenderContext);
// Since this is only a single line, ignore the text leading in the height
double textHeight = lm.getAscent() + lm.getDescent();
double textX = x + (diameter - textBounds.getWidth()) / 2.0;
double textY = y + (diameter - textHeight) / 2.0 + lm.getAscent();
graphics.drawString(text, (int) textX, (int) textY);
}
}
Aggregations