Search in sources :

Example 1 with Gauge

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);
    }
}
Also used : Origin(org.apache.pivot.wtk.Origin) BasicStroke(java.awt.BasicStroke) Color(java.awt.Color) Rectangle2D(java.awt.geom.Rectangle2D) Dimensions(org.apache.pivot.wtk.Dimensions) Gauge(org.apache.pivot.wtk.Gauge) FontRenderContext(java.awt.font.FontRenderContext) LineMetrics(java.awt.font.LineMetrics)

Aggregations

BasicStroke (java.awt.BasicStroke)1 Color (java.awt.Color)1 FontRenderContext (java.awt.font.FontRenderContext)1 LineMetrics (java.awt.font.LineMetrics)1 Rectangle2D (java.awt.geom.Rectangle2D)1 Dimensions (org.apache.pivot.wtk.Dimensions)1 Gauge (org.apache.pivot.wtk.Gauge)1 Origin (org.apache.pivot.wtk.Origin)1